2013-04-26 4 views
1

인터페이스가 있습니다 (추상 클래스 일 수도 있음). 구현자가 특정 기능을 지원하는지 여부를 지정할 수 있어야하며 가장 좋은 방법을 찾고 있습니다. 그것을 달성하십시오.계약에서 기능이 지원되는지 여부를 지정하는 방법

몇 가지 선택이 여기에 있습니다 :

BCL 보면 내가 할 경우, 나는 Stream 클래스가 기능이 지원되는지 확인하는 데 사용할 수 있습니다 CanReadCanSeek 같은 속성을 가지고 있으며, NotSupportedException 던졌습니다 참조 지원되지 않는 것. 내가 또는 지원되지 않을 수있는 몇 가지 기능보다는 이상을 가지고 있고 각 하나에 대한 "SupportsX"속성을 정의하지 않으려는하지만

public interface IHandler { bool SupportsA { get; } bool SupportsB { get; } void A(); void B(); } 

은 나를 위해 적절한 방법이 될 것입니다.

는 또한 비트 Enum 값을 매우 좋아 그리고 난 또 다른 방법이 될 것이라고 생각한다

[Flags] 
public enum HandlerFeature 
{ 
    None = 0 
    A = 1, 
    B = 2, 
    C = 4 
} 

public interface IHandler 
{ 
    HandlerFeature Features { get; } 

    void A(); 
    void B(); 
    void C(); 
} 

그리고이 같은 확장 방법을 쓸 수있다 :
bool Supports<T>(this T handler, HandlerFeature feature) where T : IHandler

내가 생각하는 어떤 다른 접근법보다 훨씬 더 낫지 만, 도울 수는 없지만 모든 Enum 값이 계약의 구성원과 일치 할 경우 해당 멤버를보다 명확하게 표시 할 수 있어야한다고 생각합니다. 그럼 난 속성에 대해 생각 : 나는 런타임에서이 같은 속성을 활용하는 방법을 알고하지 않지만

public interface IHandler 
{ 
    [HandlerRequires(Feature.None)] 
    HandlerFeature Features { get; } 

    [HandlerRequires(Feature.A)] 
    void A(); 

    [HandlerRequires(Feature.B)] 
    void B(); 

    [HandlerRequires(Feature.A | Feature.B)] 
    void AB(); 

    [HandlerRequires(Feature.C)] 
    void C(); 
} 

, 그것은 확실히 인터페이스 정의가 충분히 명시 적 보이는 있습니다.

모범 사례가 있습니까?
아니면 다른 방법을 권하고 싶습니까?
내가 지정한 것과 관련된 문제가 있습니까?

+1

http://en.wikipedia.org/wiki/Interface_segregation_principle – Ani

답변

1

이 모든 것을 사용해야하는 인터페이스를 작성해야하는 경우 개발자가 해당 인터페이스를 구현할 때 개발자가 해당 속성의 값을 지정해야하기 때문에 Booleans를 사용하는 것이 좋습니다. 신고 된 enum이나 속성을 사용하면 클래스가 생성 될 수 있습니다. 메소드 A가 구현되지 않았지만 개발자가 Attribute 또는 enum을 올바르게 설정하는 것을 잊어 버렸습니다. 이 경우 컴파일러에서 오류가 발생하지 않습니다.

어쨌든, 나는 그러한 "뚱뚱한"인터페이스를 구성하지 말 것을 권한다. 나는 당신이 객체 지향 디자인의 솔리드 원칙의 일부인 "Interface Segregation Principle"에 대해 읽도록 권합니다. (Google에서는 여러 기사를 찾을 것입니다.) 그것은 클라이언트가 사용하지 않는 방법에 의존하도록 강요되어서는 안된다고 명시합니다. 결과적으로 여러 측면을 밀어 넣는 인터페이스 대신 여러 개의 작은 인터페이스를 사용하게됩니다. 이제 귀하의 작업 내용을 알 수 없지만 인터페이스에 여러 가지 문제가 통합되어 있다면 기본 비즈니스 기능 외에도 로깅을 사용하려면 인터페이스 로깅을 중단하고 Decorator 패턴을 사용하는 것이 좋습니다 (또한 Google에서는 모르는 경우이를 사용합니다 :-)).

희망이 도움이됩니다.

+1

+1 그리고 예, Ani의 의견도 함께 왔습니다.당신이 옳고 나는 완전히 동의합니다. 그러나 제 시나리오에서는 정말로 그렇게 뚱뚱하지 않습니다 * : 그리고 속성에 관해서는, 구현자가 그것을 사용하게 만들려는 의도가 결코 아니 었습니다. 나는 그것을 사용하는 것으로 벗어나기를 희망했습니다. 여하튼 계약. 그리고 언급 한 개념에 감사드립니다. –

+0

하나의 인터페이스 유형을받는 코드가 존재하는 경우 종종 다른 인터페이스의 기능을 사용하려는 경우, 이전 인터페이스에 해당 기능과 연관된 메소드가 포함되는 것이 유리할 수 있습니다. 예를 들어'IEnumerable '은 무엇인가 제한되어 있는지, 빠르게 셀 수 있는지, 아니면 아무 것도 아닌지를 알려주는 속성을 'Count()'메소드와 함께 포함하고있다. 만약 아무것도 없다면'Enumerable .CountByEnumeration (this) '(제한이있는 경우) 또는'NotSupportedException' (제한이없는 경우)을 던져서'ICollection'으로 시도해 보는 것보다 깔끔하게 될 것입니다. – supercat

+0

@supercat : 저는 동의하지 않습니다. 유한 수의 항목이있는 열거 형을 원한다면 IElumerable 대신 IReadOnlyCollection 또는 IReadOnlyList 인터페이스를 사용하십시오. 그렇지 않으면 Liskov Substitution Principle을 위반하게됩니다. Mark Seemann은 이에 대한 흥미로운 블로그 항목을 작성했습니다 : http://blog.ploeh.dk/2013/07/20/linq- 대 - 대 - lsp/ – feO2x