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对象。