2009-12-31 25 views
13

我有一個從CSV文件操作導入產品的類,它需要大約7個參數。這是進口商確實需要的信息。混合基於構造函數和基於setter的注射是一件壞事嗎?

所有這些參數具有相同的使用壽命。最後,我們必須有一個Immutable Object

我太害怕,無法全部列的,因爲它會影響到可讀性構造函數,決定將其中3至setter方法注射。但顯然這不是一個優雅的解決方案。

問題:

1)混合是基於構造函數和setter基於注射一種不好的做法?

2)如何解決這個問題?

我在想由Martin Fowler將「引入參數對象」重構,但有一個問題與此有關。

4參數可以被移動到參數對象很容易(客戶ID,專案編號,languageId等) - 所有的整數。

其他3個參數是我注入的對象(它是模擬單元測試所必需的)。

+0

這將取決於您的DI容器...有些使這比其他更容易。 – skaffman 2009-12-31 15:10:37

+4

@skaffmann:我非常不同意。 DI模式的使用不應該由DI容器的選擇來決定 - 容器可以幫助你,而不是限制你。 – 2009-12-31 15:26:27

+0

@Nikita - 爲什麼不引入完整的參數對象並將你的模擬注入參數? – 2009-12-31 15:36:30

回答

22

它不一定是壞事混合構造器注入和財產注射,但它可能不會是普遍的。作爲一個整體策略,避免使用屬性注入是因爲它更難以正確實現(這聽起來可能違反直覺,但這是事實)。

瞭解何時使用每種模式很重要。

  • 構造函數注入應該是你的默認注入模式。它非常容易實現,並且可以保證不變式:將其分配給只讀字段以確保消費者的不變量。
  • 當您擁有良好的本地默認值實現時,可以使用屬性注入,但您希望遵循Open/Closed Principle,並允許高級用戶通過提供替代實現來擴展該類。

你不應該適用,因爲構造化妝品的屬性注射。

當您需要太多的依賴關係時,這表示您可能違反了Single Responsibility Principle - 該班級只是一次性嘗試過多。

相反引入參數對象(否則一個很好的建議)的,更好的選擇是封裝的兩個或更多的依賴關係爲聚集服務即編排這些依賴的相互作用。

試想一下,你最初的構造是這樣的:

public MyClass(IDep1 dep1, IDep2 dep2, IDep3 dep3, IDep4 dep4, IDep5 dep5) 

應用位分析後,你搞清楚,在這種情況下IDep1,IDep3和IDep4將一起以特定方式使用。這將使您能夠引進封裝這些像這樣的聚合服務:

public class AggService : IAggService 
{ 
    public AggService(IDep1 dep1, IDep3 dep3, IDep4 dep4) 
    { 
     // ... 
    } 

    // ... 
} 

您現在可以改寫原來的構造函數是:

public MyClass(IAggService aggSrvc, IDep2 dep2, IDep5 dep5) 

等等...

它非常普遍的是,總體服務本身就是一個合適的概念,並且突然間,您擁有比開始時更豐富的API。

+0

聚合服務與參數對象有何不同?這聽起來像是你建議它可能與領域模型有更具表現力的具體關係,但這應該是設計良好的參數對象的真實情況,不是嗎? – 2009-12-31 15:32:50

+0

非常清晰和有趣。很好的答案。謝謝,馬克! – ep3static 2009-12-31 15:38:07

+0

@Jeff Sternal:聚合服務可能與參數對象差別不大,但聚合服務更傾向於好萊塢原則(好東西)。參數對象通常只是包含可以單獨提取和使用的相關對象的結構。彙總服務將隱藏消費者的這些依賴關係,而是提供整體功能。雖然... – 2009-12-31 15:56:06

相關問題