9

听了Clean Code Talks之后,我明白了我们应该使用工厂来组合对象。因此,例如,如果 aHouse具有 aDoor并且 aDoor具有 a DoorKnob,则在HouseFactory我们创建一个 newDoorKnob并将其传递给 的构造函数Door,然后将该新Door对象传递给 的构造函数House

但是使用House (比如类名是ABC的类呢?这将取决于,对HouseFactory吧?那么我们是否HouseFactory在 的构造函数中传递ABC? 这样我们就不必在构造函数中传递大量工厂了吗?

4

3 回答 3

10

继续使用 Door 和 DoorKnob 示例,您不会注入工厂 - 您会注入 DooKnob 本身:

public class Door
{
    private readonly DoorKnob doorKnob;

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

        this.doorKnob = doorKnob;
    }
}

在这个级别上看不到任何工厂。

另一方面,House 依赖于 Door,但不依赖于 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 容器在此级别进行组合,但您不必这样做。不涉及任何工厂。

于 2012-01-24T07:29:26.347 回答
2

如果你注入了太多的工厂,那就是一种叫做构造函数过度注入的代码味道,这表明你的类做的太多了。

许多容器提供称为自动工厂的功能。这意味着Func<T>如果他们知道如何生成T.

Castle Windsor 有一个称为Typed Factory 设施的高级功能,它可以即时生成工厂接口的实现。

在TecX 项目中还有一个用于 Unity 的类型化工厂端口。

于 2012-01-24T07:08:13.707 回答
0

如果您最终使用 Unity,我最近为 Unity 实现了一个等效的 Castle Windsor Typed Factories。您可以在https://github.com/PombeirP/Unity.TypedFactories找到该项目,在 http://nuget.org/packages/Unity.TypedFactories找到 NuGet 包。

用法如下:

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

您只需使用返回 IFoo 的方法创建 IFooFactory 接口,其余的由库为您完成。您可以解析 IFooFactory 并使用它立即创建 IFoo 对象。

于 2012-12-06T21:40:59.143 回答