2014-10-10 44 views
0

我有一个问题来扩展访问者模式跨多个模块,你可以阅读评论中的问题的解释。在不修改原始源代码的情况下扩展访问者模式?

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 
    } 

} 

很显然,如果我们将放置方法getSupportedCurrencies()在东森光电 就不会有这样的问题,但它也没有我想完美的方式。

问题是,我们可以做更好的访客吗?

或者在这种情况下你会采取什么建议?

+0

您可以对基本访问者使用一些默认操作:打印日志条目和/或抛出异常以在其他地方处理。为什么你认为有更好的选择? – 2014-10-10 14:27:05

+0

因为我认为有人比我更聪明=),我也考虑过例外,但我们会等待,也许有人会想出另一个想法。 – 2014-10-10 14:37:07

+0

那么,一个选项可以使代码无需CCE:'Module2Source2 extends Module1Source1 implements IAnotherModuleSource'。但我不知道它是否可以接受。 – 2014-10-10 14:42:26

回答

1

铊;博士:您所描述的问题是试图将模式应用到它不适合一个问题的结果。

“的理由来改变”都属于两个基本种类:数据和功能。访问者模式将数据和功能之间的正常OO直接关联分离开来,这种方式可以让您牺牲改变数据结构的能力,以换取能够非常轻松地更改功能的交换。添加另一个ISourceVisitor将是微不足道的,因为这就是Visitor模式的设计目的。添加另一个ISource会更改您的数据结构,并强制您更改所有功能以适应该功能,这是您选择了错误模式的明确标志。

相关问题