2011-08-13 73 views
5

我試圖用IoC,DI和OOD更好地實現更好的可測試性和更寬鬆的耦合。使用IoC容器的OOD - 如何構造依賴對象?

所以,當我們大量使用的IoC和DI設計類,我們可以用多依賴的類endup例如

class Processor 
{ 
    private IService1 m_Service1; 
    private IService2 m_Service2; 
    private IService3 m_Service3; 

    //approach 1 
    public Processor(IService1 service1, IService2 service2, IService3 service3) 
    { 
     m_Service1 = service1; 
     m_Service2 = service2; 
     m_Service3 = service3; 
    } 
    //approach 2 
    public Processor(IContainer container) 
    { 
     m_Service1 = container.Resolve<IService1>(); 
     m_Service2 = container.Resolve<IService2>(); 
     m_Service3 = container.Resolve<IService3>(); 
    } 

    //approach 3 
    public delegate Processor Factory(); 

} 

林想什麼應該是通常的做法在這裏。我們可以把構造與3個參數,但是,如果我們正在建設使用autofac應用程序(例如)最有可能很少會被一些容器實例解析類型,如

Processor proc = new Processor(
container.Resolve<IService1>(), 
container.Resolve<IService2>(), 
container.Resolve<IService3>()); 

所以我想,也許方法可以使用其他比2更好,當我們從容器取決於多種類型。無論如何,我們將不得不在某處添加對autofac的引用,所以有什麼理由不這樣做呢?

Autofac還提供委託工廠方法方法

http://code.google.com/p/autofac/wiki/DelegateFactories

var processorFactory = container.Resolve<Processor.Factory>(); 
Processor processor = processorFactory.Invoke(); 

所以我們也接近3 - 我們將不使用構造函數來創建我們的類的實例,相反,我們將調用從容器解決委託它會解決我們的依賴關係。

由於即時通訊對IoC來說相當新穎,所以很難說我們應該使用1,2,3。他們有優點和缺點。

我認爲一般如果類有1依賴我們可能總是使用方法1 ..除此之外,我真的不知道該選擇什麼時候。

UPDATE我已閱讀服務定位器反模式,但香港專業教育學院拿出4(或真第三屆方法)

其接近服務定位,除了它不是,我們通過一個對象,它看起來像這樣

public class ServiceLocatorObject 
{ 
     private IService1 m_Service1; 
     private IService2 m_Service2; 
     private IService3 m_Service3; 
     public IService1 Service1 {get {return m_Service1;}} 
     public IService2 Service2 {get {return m_Service2;}} 
     public IService3 Service3 {get {return m_Service3;}} 

     public ServiceLocatorObject(IService1 service1, IService2 service2, IService3 service3) 
     { 
      m_Service1 = service1; 
      m_Service2 = service2; 
      m_Service3 = service3; 
     } 
} 

現在我們創建

//approach 4 
public Processor(ServiceLocatorObject servicesToUse) 
{ 
    m_Services = servicesToUse; 
} 

現在,我們已經從服務實現中解耦我們班的d清楚它需要什麼真正的依賴關係(如果我們假設需要所有可用的服務),因爲我們沒有傳遞一個容器可以包含100個實現。如果在我們的應用程序的某個其他類中可能需要3個服務組合,那麼該對象甚至可以重用。所以我們使用構造函數DI而不是ServiceLocator模式。界面清晰並且不會與依賴關係重疊,新類可能是一個很好的重用候選項。

你會說這個嗎?

回答

6

現在服務位置模式通常被認爲是反模式(使用container.Resolve和注入容器)。

很多人在爲這個概念而掙扎並試圖決定我是否喜歡它或討厭它之後,我已經意識到我同意服務位置是一種反模式 - 因爲它混淆了存在的相互依賴關係,這是面向對象的核心概念。

有一個在這裏閱讀: http://blog.ploeh.dk/2010/02/03/ServiceLocatorIsAnAntiPattern.aspx

其實我喜歡這一事實,在選項1,流程明確表示其對每次列表是在構造函數中的參數服務的依賴。它使得依賴非常明顯....並且我認爲它有助於促進良好的設計。

只是說處理器需要一個IContainer並不能告訴我們很多...因此您需要仔細觀察以確定相互依賴關係。

+0

鏈接很好,那本書看起來正是我所需要的。你對第三種方法有什麼看法? –

+0

+1請參閱我的回答以獲取進一步的意見。 –

+1

我使用第三種方法遍及我的代碼......當我需要注入一種方法來隨着時間的推移創建一個類型的許多實例。我使用Windsor ...所以我使用了很多委託工廠,並且當我知道我的處理器需要隨着時間的推移創建許多IService1時,會注入Func ... – Jeff

0

這不是關於數量的依賴關係,也不是每個類別的決定。方法2引入了新的依賴關係,但是如果您想依賴IoC容器,則不是一種好方法。方法3與第二種方法類似,但讓我們今後在工廠中做一些事情。方法1最簡單,不依賴於任何東西,應該用於通常不通過IoC容器管理的依賴項。

+0

這不是多個依賴性的,也不是每個班的決定。 - 你能詳細說明一下嗎?所以我們應該選擇整個應用的單一方法,並在任何地方使用它,或者你在說什麼?我不確定爲什麼它不能成爲每個班級的決定。 –

+0

使用IoC容器的選擇會影響整個應用程序 - 每個模塊都應該依賴它。方法1很自然 - 所有開發人員都瞭解它。方法2是容器特定的。你能做的最糟糕的事情就是混合它們。代碼的讀者將不得不檢查哪個appraoch被使用,同樣適用於測試作者。 –

6

通過JeffN825給出的答案是正確的,但我想補充它,你從來沒有用這樣的容器創建新的處理器實例:

Processor proc = new Processor(
    container.Resolve<IService1>(), 
    container.Resolve<IService2>(), 
    container.Resolve<IService3>()); 

相反,你讓容器自動線的依賴關係和resolve it one go

Processor proc = container.Resolve<Processor>(); 
+0

謝謝,Mark。你能否說一下第三種方法?什麼情況下,當它比你的建議處理器更好proc = container.Resolve ();或第一種方法? –

+1

第三種方法只是一個僞裝的抽象工廠:http://blog.ploeh.dk/2009/05/28/DelegatesAreAnonymousInterfaces.aspx這與其他兩種方法沒有什麼關係。你會用它做什麼? –

+0

嘿馬克,ive在閱讀你的一些帖子後添加了一個更新問題,你怎麼看待它? –