2014-10-10 5 views
0

Visitor 패턴을 여러 모듈로 확장하는 데 문제가 있었기 때문에 주석의 설명을 읽을 수 있습니다. 우리는 방법 getSupportedCurrencies를 배치 할 경우원본 소스 코드를 수정하지 않고 방문자 패턴을 확장 하시겠습니까?

interface Example { 

    interface ISource { 
     Object accept(ISourceVisitor visitor); 
    } 

    class Module1Source1 implements ISource { 
     @Override 
     public Object accept(ISourceVisitor visitor) { 
      return visitor.visit(this); 
     } 
    } 

    class Module1Source2 implements ISource { 
     @Override 
     public Object accept(ISourceVisitor visitor) { 
      return visitor.visit(this); 
     } 
    } 

    interface ISourceVisitor { 
     Object visit(Module1Source1 wheel); 
     Object visit(Module1Source2 engine); 
    } 

    class SupportedCurrenciesVisitor implements ISourceVisitor { 
     @Override 
     public Object visit(Module1Source1 wheel) { 
      return ImmutableList.of("USD"); 
     } 

     @Override 
     public Object visit(Module1Source2 engine) { 
      return ImmutableList.of("EUR"); 
     } 
    } 

    //suppose we don't want to change the code above because it's in another library 
    //I want to add one more source 

    class Module2Source1 implements ISource { 
     @Override 
     public Object accept(ISourceVisitor visitor) { 
      return null; 
     } 
    } 

    // I cannot change ISourceVisitor, so what do I need to do? 
    // one way is to create another interface 

    interface IAnotherModuleSource extends ISource { 
     Object accept(IThisModuleSourceVisitor visitor); 
    } 

    interface IThisModuleSourceVisitor extends ISourceVisitor { 
     Object visit(Module2Source2 module2Source2); 
    } 

    class Module2Source2 implements IAnotherModuleSource { 
     //it's ok 
     @Override 
     public Object accept(IThisModuleSourceVisitor visitor) { 
      return visitor.visit(this); 
     } 
     //but what should we do with this:?? 
     @Override 
     public Object accept(ISourceVisitor visitor) { 
      return accept((IThisModuleSourceVisitor) visitor); 
     } 

     //this way if SupportedCurrenciesVisitor will be passed to the Module2Source2 we 
     //will have CCE 
     //but it's ok if we pass here specific visitor for this module 
    } 

} 

분명히()는 Isource 에 그런 문제가 없을 것이다, 그러나 그것은 또한 내가 생각 완벽한 방법이 아니다.

방문자와 함께하는 것이 더 좋은가요?

또는이 상황에서 제안 된 접근 방법은 무엇입니까?

+0

기본 방문객 : 인쇄 로그 항목에 대한 일부 기본 작업을 사용하거나 다른 곳에서 처리 할 예외를 throw 할 수 있습니다. 왜 더 나은 옵션이 있다고 생각하니? –

+0

나는 거기보다 더 똑똑한 사람이 있다고 추정하기 때문에 예외도 고려했지만 우리는 기다릴 것입니다. 아마도 누군가 다른 아이디어를 내놓을 것입니다. –

+0

글쎄, CCE없이 코드 작업을 할 수있는 한 가지 옵션은'Module2Source2 extends Module1Source1 extends IAnotherModuleSource'입니다. 그러나 그것이 당신에게 받아 들여질 수 있는지 나는 모른다. –

답변

1

Tl; dr : 설명하는 문제는 적합하지 않은 문제에 패턴을 적용하려고 시도한 결과입니다.

"변경해야 할 이유"는 모두 데이터와 기능의 두 가지 기본 범주로 나뉩니다. 방문자 패턴은 기능을 매우 쉽게 변경할 수있는 대가로 데이터 구조를 변경하는 기능을 희생하게하는 방식으로 데이터와 기능간에 일반적인 OO 직접 연결을 분리합니다. ISourceVisitor을 추가하는 것은 사소한 일인데, 그 이유는 방문자 패턴이 당신을 그렇게하도록 설계 되었기 때문입니다. 또 다른 ISource을 추가하면 데이터 구조가 변경되고이를 수용하기 위해 모든 기능을 변경해야하므로 잘못된 패턴을 선택했다는 확실한 신호입니다.