Инъекция конструктора-мы также вводим заводы?


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

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

3 9

3 ответа:

Оставаясь с дверью и дверной ручкой, вы не вводите фабрику - вы вводите саму ручку:

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;
    }
}

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

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

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

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

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

Замок Виндзор имеет расширенную функцию под названиемтипизированные заводские средства , которая генерирует реализации Заводского интерфейса на лету.

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

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

Используется следующее:

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

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