2011-08-26 44 views
8

根據SOLID原則,類不能依賴其他類,必須注入依賴關係。這很簡單:依賴倒置。對象創建

class Foo 
{ 
    public Foo(IBar bar) 
    { 
     this.bar = bar; 
    } 

    private IBar bar; 
} 

interface IBar 
{ 
} 

class Bar: IBar 
{ 
} 

但是,如果我想我的Foo類能夠創建酒吧,不知道在IBar後面的確切實現? 我能想到的在這裏4級的解決方案,但他們似乎有缺點:

  1. 注入對象的類型和使用反射
  2. 使用泛型
  3. 使用「服務定位器」,並呼籲決心( ) 方法。
  4. 創建分離工廠類,並將其注入到富:

class Foo 
{ 
    public void DoSmth(IBarCreator barCreator) 
    { 
     var newBar = barCreator.CreateBar(); 
    } 
} 

interface IBarCreator 
{ 
    IBar CreateBar(); 
} 

class BarCreator : IBarCreator 
{ 
    public IBar CreateBar() 
    { 
     return new Bar(); 
    } 
} 

最後一種情況似乎很自然,但BarCreator類有過痘痘的代碼。 那你怎麼看,哪個最好?

+1

選項4是正確答案:http://stackoverflow.com/questions/1943576/is-there-a-pattern-for-initializing-objects-created-via-a-di-container/1945023#1945023 –

+1

但是,爲什麼你想讓Foo創建IBar?注意泄漏抽象。 –

回答

0

我覺得當你說「我希望我的Foo課堂能夠創建酒吧」時,還有一個規則就是「分離關注點」。所以你應該將創建類的任務委託給其他人,Foo不應該擔心這個任務。

2

這一切都取決於您的確切場景和您的需求。
我認爲最常用的方法,正如你所說的,factory
如果您使用IoC框架(如Ninject或Sprint.Net,Castle Windsor等,請參閱here),服務定位器也是一個可行的解決方案。

3

我喜歡在這種情況下「注入」Func<IBar>。像這樣:

class Foo 
{ 
    public Foo(Func<IBar> barCreator) 
    { 
     this.bar = barCreator(); 
    } 

    private IBar bar; 
} 

interface IBar 
{ 
} 
2

如果您的冗餘工廠接口有問題,您可以在這裏採取兩種方法。

使其可重複使用泛型:

interface IFactory<T> 
{ 
T Create(); 
} 

class DefaultConstructorFactory<T> : IFactory<T>, where T: new() 
{ 
public T Create() { return new T();} 
} 

或者使用匿名函數作爲一個工廠:

public void DoSomething(Func<IBar> barCreator) 
{ 
var newBar = barCreator(); 
//... 
} 
+0

這實際上不工作嗎?您不能將'DefaultConstructorFactory '作爲'IFactory ' – fearofawhackplanet

3

這就是工廠被用於製成。

如果您覺得您的工廠代碼太少,請問問自己,您只需創建內聯實例就可以帶來哪些好處。如果這些好處超過了添加的代碼的成本,那麼請不要擔心。

我會親自避免服務地點,或者如果您真的必須使用它,我會將它隱藏在工廠後面。服務地點往往容易被濫用,並可能導致您的容器找到它應該沒有任何關係的代碼。

爲方便起見,某些容器允許您指定容器在創建組件實例時使用的工廠。在這種情況下,你的班級可能直接依賴於IBar,但是當你的班級需要一個新的實例時,你的班級將會撥打IBarCreator。例如,溫莎城堡在其API中具有方法UseFactoryUseFactoryMethod