1

아래와 같이 인터페이스 패턴에서 읽기 및 쓰기 액세스를 분리하려고한다고 가정합니다.필드에 대한 읽기/쓰기 액세스 제어

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); } 
    } 
} 

구현 :

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; } 
     } 

    } 
} 

우리가 상속 해, 우리가 가서 그것을위한 인터페이스를 정의하는 다른 클래스가 필요하다고 가정 해 보겠습니다 :

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

이 쉽게 구현할 수있다 이것은 그렇게 쉬운 일이 아닙니다. Writable.B는 반복적 인 코드를 피하기 위해 Writable.A와 ReadOnly.B라는 두 개의 기본 클래스에서 상속해야한다고 항상 생각합니다.

사용할 권장 디자인 패턴이 있습니까? 목표는 요구 사항에 따라 "읽기 전용 액세스"및 "읽기 쓰기 액세스"객체를 개별적으로 반환 할 수 있도록하는 것입니다 (컴파일 타임에 결정됨). 솔루션 패턴으로 상속 계층, 클래스 C, D를 더 쉽게 추가 할 수 있다면 좋을 것입니다 ...

다중 상속 문제는 여기에서 다루고 있으며, 다른 곳에서도 논의 된 바 있습니다. 많은, 많은, 장소. 하지만 내 질문에 너무 많은 "어떻게 상속을 사용하지 않고 네임 스페이스 accesspattern 내부에 정의 된 인터페이스를 구현하는"(비록 내가 그 최선의 방법을 배우고 싶지만)보다는 오히려, 우리는 어떻게 정의 할 수 ReadOnly/클래스의 쓰기 가능 버전과 별도로 클래스를 생성하지 않고도 상속을 지원합니다.?

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"뷰만 사용하도록 요구하는 알고리즘을 구현할 수 있습니다.이 뷰는 함수가 상태 회피에서 변경을 초래할 수 있음을 의미합니다.

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 
     } 
    } 
} 
+0

는 사용할 수 없습니다 속성을? 각각의'get'과'set'에 대한 접근을 개별적으로 지정할 수 있습니다. 또한 List <>에는 AsReadOnly()가 있다는 것을 기억합니다. 어쩌면 비슷할 수도 있지만 쓰기 가능한 클래스에서 호출해야합니다. BTW, 수업을 명확하게 분리하는 이유는 무엇입니까? – cyanic

+0

우리는 어떻게 클래스의 ReadOnly/Writable 버전을 개별적으로 정의 할 수 있으며 상속을 매우 어렵게하지 않고도 지원할 수 있습니까? - 쓰기 및 읽기 액세스 용으로 두 개의 인터페이스를 작성하고 한 클래스에서 상속해야하며 필요한 클래스 버전을 선택하는 fabrica를 작성해야합니다. Fabrica는 필요한 인터페이스를 통해 클래스의 인스턴스를 반환합니다. 그게 다야. –

+0

@GMMan get set 속성을 사용하면 xml serialization 사용을 배제합니까? http://msdn.microsoft.com/en-us/library/182eeyhh%28VS.85%29.aspx? – user859400

답변

0

엔터티 수준이 아닌 서비스 수준에서 읽기/쓰기 액세스 권한을 제공 할 수 있습니다. 이 경우 코드는 읽기/쓰기 액세스를 처리하는 서비스 주위에 래퍼 인을 생성 할 수 있습니다. 패턴 사용 : 실내 장식, 의존성 삽입 (Dependency Injection)

+1

제안에 감사드립니다. 나는 당신이 논평하는 것은 제안이지만 대답이 아니라고 생각합니다. 답변이 아니라 의견으로 배치해야합니까? 어쨌든, 내가 게시의 하단에 귀하의 의견을 올린 코드에 대해 어떻게 생각하십니까? 그것은 당신이 제안하는 것과 비슷합니까? 그렇지 않다면 인터페이스를 구현하기위한 예제 코드를 제공 할 수 있습니까? 감사. – user859400

1

나는이 스레드가 한 살 알고 있지만, 이런 식으로 뭔가해야 할 말이 것인지 궁금하네요 :

interface ReadOnlyA 
{ 
    object A { get; } 
} 

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

누군가에게'ReadOnlyA'로 위장한'WriteableA' 인스턴스를 제공합니다. 그리고 그들은 그것을 단지'WriteableA'에 던져서 수정합니다. –

+0

글쎄, 그것은 다릅니다. 쓰기 액세스를 실제로 제어하는 ​​경우 대부분 WriteableA 인터페이스는 내부적이며 ReadOnlyA 인터페이스 만 공용이므로 캐스팅하지 않습니다. –

+0

외부 개발자가'ReadOnlyA'와'WriteableA' 둘 다 사용할 수있는 라이브러리 시나리오가 있습니다. 이것은 콜렉션에 일반적입니다. 추신 내 비슷한 질문에 중복을 검색하는 동안이 질문을 찾았습니다. http://stackoverflow.com/questions/24216616/an-object-that-securely-provides-both-public-api-read-only-and-private-api-re/ –

관련 문제