Внедрение в конструктор - Мы также вводим фабрики?

После прослушивания разговоров о чистом коде я понял, что мы должны использовать фабрики для составления объектов. Так, например, если House имеет Door и Door имеет DoorKnob, в HouseFactory мы создаем новый DoorKnob и передать его конструктору Door, а затем передать этот новый Door возражать против конструктора House,

Но как насчет класса, который использует House (скажем, имя класса ABC ) Это будет зависеть от HouseFactory, право? Так мы передаем HouseFactory в конструкторе ABC? Разве мы не должны передать таким образом множество фабрик в конструктор?

3 ответа

Решение

Оставаясь с примером Door и DoorKnob, вы не вводите фабрику - вы вводите сам DooKnob:

public class Door
{
    private readonly DoorKnob doorKnob;

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

        this.doorKnob = doorKnob;
    }
}

На этом уровне не видно заводов.

Дом, с другой стороны, зависит от Door, но не от DoorKnob:

public class House
{
    private readonly Door door;

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

        this.door = door;
    }
}

Это сохраняет опции открытыми до тех пор, пока, наконец, вам не придется составлять все в корне композиции приложения:

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

Вы можете использовать DI-контейнер для компоновки на этом уровне, но это не обязательно. Фабрики не участвуют.

Если вы внедряете слишком много фабрик, это запах кода, называемый чрезмерным внедрением конструктора, который указывает, что ваш класс делает слишком много.

Многие контейнеры предоставляют функцию, называемую автофабриками. Это означает, что они генерируют фабрики типа Func<T>автоматически, если они знают, как генерировать T,

Castle Windsor имеет расширенную функцию, называемую Typed Factory, которая генерирует реализации фабричного интерфейса на лету.

В проекте TecX также есть порт типизированных фабрик для Unity.

Если вы в конечном итоге используете Unity, я недавно реализовал эквивалент фабрики Castle Windsor Typed Factories для Unity. Вы можете найти проект по адресу https://github.com/PombeirP/Unity.TypedFactories, а пакет NuGet - по адресу http://nuget.org/packages/Unity.TypedFactories.

Использование следующее:

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

Вам просто нужно создать интерфейс IFooFactory с методом, возвращающим IFoo, а остальное сделает библиотека. Вы можете разрешить IFooFactory и сразу использовать его для создания объектов IFoo.

Другие вопросы по тегам