2012-01-12 87 views
2

我對適配器類毫無疑問。我知道適配器類的目標是什麼。何時應該使用。我的疑問是關於班級建設。我查了一些教程,他們都說我應該將「Adaptee」類作爲依賴項傳遞給我的「Adapter」。 例如適配器模式和依賴關係

Class SampleAdapter implements MyInterface 
{ 
    private AdapteeClass mInstance; 
    public SampleAdapter(AdapteeClass instance) 
    { 
     mInstance=instance; 
    } 
} 

這個例子複製自wikipedia。正如你所看到的,AdapteeClass作爲依賴被傳遞給我的對象。問題是爲什麼?如果我改變對象的界面很明顯,我將使用「新」界面,我不需要「老」界面。爲什麼我需要在適配器外部創建「舊」類的實例。有人可能會說我應該使用依賴注入,所以我可以通過我想要的任何東西,但這是適配器 - 我需要更改具體類的接口。就我個人而言,我認爲下面的代碼更好。

Class SampleAdapter implements MyInterface 
{ 
    private AdapteeClass mInstance; 
    public SampleAdapter() 
    { 
     mInstance= new AdapteeClass(); 
    } 
} 

您的意見是?

+0

我認爲你正在尋找裝飾器... – dotnetstep 2012-01-12 16:17:51

+1

@dotnetstep不,他所指的適配器模式與裝飾器不同。裝飾者將保持界面相同,但會延長行爲。適配器重新編譯現有類的接口以匹配預期的接口請參閱http://stackoverflow.com/questions/350404/how-do-the-proxy-decorator-adaptor-and-bridge-patterns-differ以獲取更多信息 – 2012-01-12 16:22:42

回答

7

我會說,當涉及到複雜對象(除非類是BuilderFactory)以減少耦合並使您的代碼更好地測試時,您應該始終避免類中的新運算符。可以在類方法(這可能是類方法的目的!)內構造類似List或Dictionary或值對象的課程對象

可以說例如您的AdapteeClass是Remote Proxy。如果你想使用單元測試,你的單元測試將不得不使用真正的代理類,因爲在你的單元測試中沒有辦法替代它。

如果您使用第一種方法,在運行單元測試時可以輕鬆地將模擬或僞造注入構造函數,以便可以測試所有代碼路徑。

谷歌有一個guide on writing testable code其描述得更詳細,但一些重要的點是:

警告標誌爲未測試的代碼

    在構造函數或字段聲明
  • 新的關鍵字
  • 在構造函數或現場聲明中的靜態方法調用
  • 構造函數中除字段賦值之外的任何內容
  • 對象的構造完成後不完全初始化(注意初始化方法)在構造
  • 控制流(條件或循環邏輯)
  • 代碼並構造內複雜的對象圖結構,而不是使用一個工廠或助洗劑
  • 添加或使用初始化塊
+0

對不起,我不買它 - *你應該**總是**避免班級中的新操作員(除非班級是建築師或工廠)* - 完全可以閱讀我的回答「是否是新操作員的惡意? !」 - 它在這裏http://stackoverflow.com/questions/8690720/factory-design-pattern-and-keyword-new/8693412#8693412 – dantuch 2012-01-12 16:26:46

+1

我同意避免在一個班的新操作員和聯結。但適配器的目標是改變給定類的接口。換句話說,兩個類必須耦合。無論如何,你是對的嘲笑。 – Ivan 2012-01-12 16:53:17

+1

同意。適配器的目的是使一個接口適應另一個接口;建設是另一個責任。在適配器內新建實例的那一刻,您將失去編程到接口的能力,並且您還顯式設置適配器實例的所有權/生命週期。這些都是可能需要在別處控制的事情(例如在DI容器中)。 – 2012-01-12 18:00:10

1

AdapteeClass可以具有一個或多個非平凡構造函數。在這種情況下,您需要在構造函數SampleAdapter中複製所有這些元素以具有相同的靈活性。傳遞已構造的對象更簡單。

0

我認爲在適配器內部創建Adaptee是有限制的。如果有一天你想調整一個預先存在的實例呢?

說實話,儘管如此,我會盡可能地做到這一點。

Class SampleAdapter implements MyInterface 
{ 

    private AdapteeClass mInstance; 

    public SampleAdapter() 
     : base (new AdapteeClass()) 
    { 
    } 

    public SampleAdapter(AdapteeClass instance) 
    { 
     mInstance=instance; 
    } 
}