Заменяет ли контейнер IoC использование фабрик - PullRequest
9 голосов
/ 12 ноября 2008

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

У меня есть такой код в приложении

internal static class StaticDataHandlerFactory
    {
        public static IStaticDataHandler CreateHandler(StaticDataUpdate staticDataUpdate)
        {
            if (staticDataUpdate.Item is StaticDataUpdateOffice)
            {
                return new OfficeUpdateHandler();
            }

            if (staticDataUpdate.Item is StaticDataUpdateEmployee)
            {
                return new EmployeeUpdateHandler();   
            }

            if (staticDataUpdate.Item == null)
            {
                throw new NotImplementedException(
                    string.Format("No static data provided"));
            }
            else
            {
                throw new NotImplementedException(
                    string.Format("Unimplemented static data type of {0}", staticDataUpdate.Item.GetType().FullName));
            }
        }
    }

Это простая фабрика, которая возвращает правильную стратегию обработки входных данных.

Позволит ли контейнер IoC исключить подобный код? Иными словами: позволит ли мне динамически выбирать конкретную реализацию для загрузки в зависимости от типа входного параметра?

Или я здесь с курса?

Ответы [ 5 ]

9 голосов
/ 13 ноября 2008

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

Кроме того, кажется, что код нарушает Закон Деметры . Похоже, что параметр должен иметь тип «StaticDataUpdateItem», а не «StaticDataUpdate». Учитывая это, есть довольно веский аргумент в пользу переписывания этого кода как вызова метода для StaticDataUpdateItem.

Я довольно интенсивно использовал IoC, но для создания динамических объектов все же лучше использовать абстрактный шаблон фабрики. Короче говоря, если вам не нравится идея добавления метода к самому элементу для генерации дескриптора, то, вероятно, лучше всего оставить код таким, какой он есть.

3 голосов
/ 12 ноября 2008

Ты совсем не далеко от курса; насколько я понимаю, ты довольно близко.

Способ, которым я обычно структурировал бы подобные вещи, состоит в том, чтобы превратить ваш класс Factory в ваш контейнер IoC, просто позволяя указывать возвращаемые UpdateHandlers с помощью Dependency Injection. Таким образом, вместо того, чтобы иметь в своем коде логику, которая указывает, что StaticDataUpdateOffice означает возвращать OfficeUpdateHandler, вы можете превратить свой код в простое сообщение, что StaticDataUpdateOffice возвращает то, что содержит (вновь указанная) переменная m_officeUpdateHandler; до тех пор, пока ваш Framework гарантирует, что вы установили значение m_officeUpdateHandler, прежде чем вызывать свою фабрику, все в порядке. И вы можете изменить значение m_officeUpdateHandler на все, что захотите во время выполнения по мере изменения ваших потребностей.

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

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

1 голос
/ 12 ноября 2008

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

public static IStaticDataHandler CreateHandler<T>( params object[] args )
{...

где аргументы могут передаваться в качестве аргументов ctor (например, в Activator).

1 голос
/ 12 ноября 2008

Короткий ответ - да, это позволяет. Это сообщение в блоге показывает отличный способ выбора реализации во время выполнения с использованием Windsor. Автор, Айенде, разрабатывает здесь и здесь .

Я еще не пробовал, но скоро ожидаю.

0 голосов
/ 11 октября 2009

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

IoC больше для конфига?

Динамическое создание объектов лучше, чем? Дженерики? Это все не по теме.

1) IoC - это просто экономия времени по сравнению с реализацией Евангелия «композиция поверх специализации / наследования».

Таким образом, правило № 1 для использования IoC заключается в том, что вам действительно надоело иметь дело с длинными конструкторами, которые следуют «привязке к контракту, а не реализации».

С другой стороны, это шаблон стратегии как альтернатива шаблону по тем же причинам (инкапсуляция ...) ... НО это больше работы для создания всех дополнительных интерфейсных / абстрактных типов, и это больше работайте, чтобы делать это КАЖДЫЙ раз со всеми IServiceProvicerThis и IResolverThat ... Если вы не устали от утомительного выполнения контрактов кода, таких как:

IInterestingService интересно = ... вы получите экземпляр однако ..

добавить еще примерно три строки, как это ..

тогда

Служба IAmazementService = новая служба AmazementService (интересно, вторая стратегия, третья и т. Д ...)

Это стареет. Таким образом, IoC никогда не является вопросом, потому что любой, кто достаточно умен, чтобы программировать с использованием надежного дизайна, будет знать лучше У тех, кто спрашивает, есть все неправильные ответы.

Так что, если вы действительно встретите вышеупомянутое, то абсолютно. Контейнеры IoC готовы выполнить столько «творческой» работы, сколько вы можете получить, если позволите им справиться с ними. И самая распространенная творческая абстракция перед явным новым - это мистер Фабрика.

Damon

...