8

聽完Clean Code Talks之後,我才明白我們應該用工廠來組成對象。因此,舉例來說,如果一個HouseDoorDoorDoorKnob,在HouseFactory我們創建了一個新的DoorKnob並把它傳遞給Door構造,然後傳遞新Door對象的House構造。構造注射劑 - 我們也注射工廠嗎?

但是如何使用House(說類名是ABC?這將取決於HouseFactory,對吧?那麼我們通過構造函數ABC中的HouseFactory?我們不是必須以這種方式在構造函數中傳遞大量工廠嗎?

回答

9

與門和門把手例如住,你不注入工廠 - 你注入DooKnob本身:

public class Door 
{ 
    private readonly DoorKnob doorKnob; 

    public Door(DoorKnob doorKnob) 
    { 
     if (doorKnob == null) 
      throw new ArgumentNullException("doorKnob"); 

     this.doorKnob = doorKnob; 
    } 
} 

沒有工廠都在視線在這個水平。

房子,而另一方面,取決於門,但不能在門把手:

public class House 
{ 
    private readonly Door door; 

    public House(Door door) 
    { 
     if (door == null) 
      throw new ArgumentNullException("door"); 

     this.door = door; 
    } 
} 

這使選擇權,到最後你在撰寫一切應用程序的Composition Root

var house = new House(new Door(new DoorKnob())); 

您可以使用DI容器在此級別撰寫,但您不需要。沒有工廠參與。

+0

感謝您的回答。一個關於構圖根的問題。當涉及到EJB調用或Web服務時,什麼應該是組合根?它是被調用的方法本身嗎? –

+0

這些是我不熟悉的Java細節,但是作爲一般概念,組合發生得非常晚:當你不可能再推遲它時。 –

1

如果注入過多的代碼氣味稱爲constructor over-injection的工廠,表明您的課程做得太多。

許多容器提供了一個稱爲自動工廠的功能。這意味着如果他們知道如何生成T,他們會自動生成Func<T>類型的工廠。

Castle Windsor擁有一項名爲Typed Factory facilities的高級功能,可以實時生成工廠界面。

TecX project也有一個港口爲鍵入Unity的工廠。

0

如果最終使用Unity,我最近實現了一個相當於Castle Windsor Type的Unity工廠。您可以在https://github.com/PombeirP/Unity.TypedFactories找到該項目,並在http://nuget.org/packages/Unity.TypedFactories處找到NuGet包。

用法如下:

unityContainer 
    .RegisterTypedFactory<IFooFactory>() 
    .ForConcreteType<Foo>(); 

你只需要創建一個返回的IFoo方法的IFooFactory接口,其餘的是由庫爲你做。您可以解析IFooFactory並使用它立即創建IFoo對象。