控制对字段的读/写访问

时间:2012-06-05 02:10:20

标签: c# design-patterns multiple-inheritance access-modifiers

假设我们想要在接口模式中分离读写访问,如下所示。

namespace accesspattern
{
    namespace ReadOnly
    {
        public interface IA { double get_a(); }
    }
    namespace Writable
    {
        public interface IA : ReadOnly.IA { void set_a(double value); }
    }
}

这很容易实现:

namespace accesspattern
{
    namespace ReadOnly
    {
        public class A : IA
        {
            protected double a;
            public double get_a() { return a; }
        }
    }
    namespace Writable
    {
        public class A : ReadOnly.A, IA
        {
            public void set_a(double value) { base.a = value; }
        }

    }
}

假设我们需要另一个继承自A的类,所以我们继续为它定义一个接口:

namespace accesspattern
{
    namespace ReadOnly
    {
        public interface IB : ReadOnly.IA { int get_b(); }

    }
    namespace Writable
    {
        public interface IB : ReadOnly.IB, Writable.IA { void set_b(int value); }
    }
}

实现这一点并非易事。人们总觉得Writable.B应该继承两个基类,Writable.A和ReadOnly.B,以避免重复代码。

是否使用推荐的设计模式?目的是能够根据需要单独返回“只读访问”和“读写访问”对象(在编译时决定)。如果解决方案模式可以轻松添加更多的继承层,类C,D ......

,那就太好了

我知道多重继承的问题在这里出现了,并且已经在许多地方的其他地方详细讨论过。但我的问题不是“如何在不使用多重继承的情况下实现在命名空间访问模式中定义的接口”(虽然我想学习最好的方法)但是,我们如何定义类的ReadOnly / Writable版本是单独的,也支持继承而不会变得非常非常混乱

这里值得的是一个(杂乱的)解决方案[见下面的更好的实现]:

    namespace accesspattern
    {
        namespace ReadOnly
        {
            public class A : IA
            {
                protected double a;
                public double get_a() { return a; }
            }
            public class B : IB
            {
                protected int b;
                public int get_b() { return b; }
            }
        }
        namespace Writable
        {
            public class A : ReadOnly.A, IA
            {
                public void set_a(double value) { base.a = value; }
            }
            public class B : ReadOnly.B, IB
            {
                private IA aObj;
                public double get_a() { return aObj.get_a(); }
                public void set_a(double value) { aObj.set_a(value); }
                public void set_b(int value) { base.b = value; }
                public B() { aObj = new A(); }
            }
        }
    }
}

更新:我认为这(以下)是尤金所说的。我认为这种实现模式非常好。通过仅传递类的“writeProtected”视图,可以实现一些算法,这些算法要求类的状态不会改变,并且只使用“writeEnabled”视图,这意味着该函数将/可能导致状态改变避免。 / p>

namespace access
{

    // usual usage is at least readable
    public interface IA { double get_a(); }
    public interface IB : IA { int get_b(); }

    // special usage is writable as well
    namespace writable
    {
        public interface IA : access.IA { void set_a(double value);  }
        public interface IB : access.IB, IA { void set_b(int value);}
    }

    // Implement the whole of A in one place
    public class A : writable.IA
    {
        private double a;
        public double get_a() { return a; }
        public void set_a(double value) { a = value; }
        public A() { }

        //support write-protection
        public static IA writeProtected() { return new A(); }
        public static writable.IA writable() { return new A(); }
    }
    // implement the whole of B in one place and now no issue with using A as a base class
    public class B : A, writable.IB
    {
        private int b;
        public double get_b() { return b; }
        public void set_b(int value) { b = value; }
        public B() : base() { }

        // support write protection 
        public static IB writeProtected() { return new B(); }
        public static writable.IB writable() { return new B(); }
    }

    public static class Test
    {
        static void doSomething(IA a)
        {
            // a is read-only
        }
        static void alterState(writable.IB b)
        {
            // b is writable
        }
        static void example()
        {
            // Write protected
            IA a = access.A.writeProtected();
            IB b = access.B.writeProtected();

            // write enabled
            writable.IA A = access.A.writable();
            writable.IB B = access.B.writable();

            Console.WriteLine(a.get_a());
            B.set_b(68);

            doSomething(A); // passed as writeprotected
            alterState(B); // passed as writable
        }
    }
}

2 个答案:

答案 0 :(得分:1)

我知道这个帖子已经有一年了,但是我想知道这样的话是否有意义:

 interface ReadOnlyA
 {
    object A { get; }
 }

 interface WriteableA : ReadOnlyA
 {
   new object A {get; set;}
 }

答案 1 :(得分:0)

您可以在服务级别而不是在实体级别提供读/写访问权限。在这种情况下,您可以代码生成围绕处理读/写访问的服务的包装器。 使用的模式:装饰器,依赖注入