Зачем использовать фабричный шаблон, когда достаточно простого внедрения зависимостей - PullRequest
0 голосов
/ 03 декабря 2018

Я смотрю на этот пример , чтобы понять, как использовать фабричный шаблон.

Я действительно любитель в этой области, поэтому извините за мой глупый вопрос.

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

В примере выше я бы сделал что-то вроде этого:

public class Program
{
    // register the interfaces with DI container in a separate config class (Unity in this case)
    private readonly IShippingStrategy _shippingStrategy;

    public Program(IShippingStrategy shippingStrategy)
    {
        _shippingStrategy= shippingStrategy;
    }

    public int DoTheWork(Order order)
    {
        // assign properties just as an example
        order.ShippingMethod = "Fedex";
        order.OrderTotal = 90;
        order.OrderWeight = 12;
        order.OrderZipCode = 98109;

        int shippingCost = _shippingStrategy.CalculateShippingCost(order);

        return shippingCost;
    }
}

Вместо того, чтобы вводить фабрику:

public class Program
{
    // register the interfaces with DI container in a separate config class (Unity in this case)
    private readonly IShippingStrategyFactory _shippingStrategyFactory;

    public Program(IShippingStrategyFactory shippingStrategyFactory)
    {
        _shippingStrategyFactory = shippingStrategyFactory;
    }

    public int DoTheWork(Order order)
    {
        // assign properties just as an example
        order.ShippingMethod = "Fedex";
        order.OrderTotal = 90;
        order.OrderWeight = 12;
        order.OrderZipCode = 98109;

        IShippingStrategy shippingStrategy = _shippingStrategyFactory.GetShippingStrategy(order);
        int shippingCost = shippingStrategy.CalculateShippingCost(order);

        return shippingCost;
    }
}

Зачем брать bruden для создания фабрики (таким образом добавляя дополнительный слой), когда мы можем внедрить интерфейс напрямую туда, где нам нужно использоватьэто?

Ответы [ 2 ]

0 голосов
/ 03 декабря 2018

Думаю, вам нужна не просто статья о заводском образце, а краткий исчерпывающий ответ.Итак, я хотел бы сосредоточиться на двух вещах.

Больше гибкости

Чаще всего вы устанавливаете корень композиции, где вы в основном говорите ...

"если кто-то хочет IAnyService, он должен получить MyAnyServiceImplementation".

Это исправлено для вашего приложения.После настройки ваш контейнер внедрения зависимостей будет обслуживать экземпляры классов, которые вы зарегистрировали, но вам не следует пытаться заново настроить этот контейнер.Это идеально подходит для гибкости запуска, например, для регистрации реализации компонентов доступа к данным в зависимости от конфигурации приложения.Скажите ...

"если кто-то хочет IUserRepository, он должен получить MsSqlUserRepository, потому что мы работаем с MSSQL-сервером".

Конечно, имея это«неизменный» корень композиции ограничивает возможности выбора реализации во время выполнения в зависимости от состояния приложений.

Вместо этого вы можете внедрить класс, который определяет текущее состояние, какую реализацию службы выбрать.Проверка данных является типичным сценарием для этого шаблона, поскольку в вашей системе могут быть разные правила для разных объектов.Модным словом здесь является «шаблон правил» или «шаблон стратегии».

Контроль времени жизни

Представьте себе экземпляр класса долгоживущего класса, такой как представление (пользовательский интерфейс) или любой присоединенный к нему класс (как модель или контроллер).Пока пользователь активен в представлении, класс жив.Например, внедрив экземпляр класса в конструктор контроллера представления, вы удерживаете его активный экземпляр в течение всего времени существования представления.

Допустим, вы хотите использовать хранилище данных, например, для подключения к базе данных.Эти вызовы для доступа к базе данных должны быть короткими, и вы не хотите держать соединения открытыми в течение длительного времени.С фабрикой репозитория вы можете очень точно контролировать время жизни и быть уверенным, что класс будет удален после его использования:

using (var repository = new _factory.CreateRepository(...))
{
    return repository.GetAnything();
}

При этом очень легкий класс - фабрика - вводится и живетпока контроллер вида живет.Тяжелые классы - вещи соединения - не должны жить долго и просто создаются при необходимости.

Фактически, есть вероятность, что хранилище вообще не создается, если нет необходимости загружать данные (из-занапример, предварительное попадание в кэш).Если бы вы внедрили репозиторий напрямую, вы гарантировали бы, что в каждом случае один долгоживущий экземпляр живет в памяти.

0 голосов
/ 03 декабря 2018

Если вы проверите код для фабрики, то увидите, что в зависимости от способа доставки заказа фабрика возвращает другую реализацию IShippingStrategy.Поскольку ShippingMethod известен только после вызова DoTheWork, невозможно внедрить правильную реализацию при создании класса (и одному и тому же классу могут потребоваться разные реализации для разных заказов).

...