2010-01-18 4 views
3

데코레이터 패턴은 가장 단순한 용어로 이해합니다. 하나의 클래스가 또 다른 클래스를 감싸고 있다는 아이디어가 있습니다. 데코레이터 메소드는 데코 레이팅 된 객체에서 같은 메소드를 호출하기 전 및/또는 호출 한 후에 다른 코드를 실행하려고합니다.세밀한 데코레이터 패턴

그러나 원하지 않는 부작용이 있기 때문에 데코 레이팅 된 메서드를 단순히 호출 할 수는 없습니다. 그러나 나는 해야합니까 그 데코 레이팅 된 방법을 많이 실행하고 싶습니다.

데코 레이팅 된 메서드를 여러 메서드로 분할 한 다음 데코레이터에서 일부를 호출하고 꾸미기 코드를 실행 한 다음 다른 메서드를 호출한다고 생각합니다. 부작용을 놓치지 않았습니다. 필요.

그러나 다형성을 유지하려면 데코 레이팅 된 객체와 장식 객체가 구현하는 인터페이스에 해당 메소드를 추가해야합니다. 이것은 바람직하지 않습니다. 그것들은 공개되어서는 안되며, 장식 된 클래스가 그것이 장식 될 방법을 알고 있다는 것을 의미합니다.

"데코레이터"가 신경 쓰는 대안 구현을 단순히 제공하는 추상 기본 클래스가 각각의 작은 메소드를 차례로 호출하는 템플릿 패턴이 더 적절할 것으로 생각합니다. 그러나 이것은 정확히 "상속을 통한 구성"이 아니므로 무엇을 권하고 싶습니까?

답변

1

API가 Command-Query Separation을 (를) 위반하는 것처럼 들리므로 최상의 옵션은 API를 다시 디자인하는 것입니다.

그러나 내가 잘못했거나 다시 디자인 할 수없는 경우 인터페이스를 변경하지 않고 장식 된 클래스의 메서드를 두 메서드로 나눌 수 있습니다.

public interface IMyInterface 
{ 
    Foo GetFoo(Bar bar); 
} 

public class MyClass : IMyInterface 
{ 
    public Foo GetFoo(Bar bar) 
    { 
     this.DoSomethingWithSideEffects(bar); 
     return this.DoSomethingToGetFoo(bar); 
    } 

    public Foo DoSomethingToGetFoo(Bar bar) 
    { 
     // ... 
    } 

    public void DoSomethingWithSideEffects(Bar bar) 
    { 
     // ... 
    } 
} 

public class MyDecorator : IMyInterface 
{ 
    private readonly MyClass mc; 

    public MyDecorator(MyClass mc) 
    { 
     // put Null Guard here... 
     this.mc = mc; 
    } 

    public Foo GetFoo(Bar bar) 
    { 
     return this.mc.DoSomethingToGetFoo(bar); 
    } 
} 

MyDecorator는 IMyInterface 대신 MyClass를 데코레이션합니다.

+1

저는 이름을 제외하고 CQS에 익숙하지 않습니다 - 어떤 방식으로 위반합니까? –

+0

나는 CQS를 위반했다고 말하지는 않지만 원치 않는 부작용은 종종 그 방향을 가리키는 표시입니다. CQS를 사용하면 메소드가 부작용이 없거나 부작용 만 * 발생합니다. 그러나 후자의 경우, 부작용은 결코 원하지 않습니다. –

2

템플릿과 같은 사운드가 자신의 시나리오에 가장 적합합니다. 나는 필요하지 않을 때 구성을 강요하지 않을 것입니다 ... this conversation은 "이 규칙에 대한 예외 : 상속을 사용해야하는 경우, 즉 대체 가능성을 모델링해야하는 경우"라고 말한 것이 가장 좋습니다.

+0

주어진 시나리오가 템플릿 패턴과 매우 유사하다고 동의합니다. –