2014-10-10 45 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會更改您的數據結構,並強制您更改所有功能以適應該功能,這是您選擇了錯誤模式的明確標誌。

相關問題