Заменяет ли контейнер IoC использование фабрик

StackOverflow https://stackoverflow.com/questions/282406

Вопрос

Я только начинаю работать с контейнерами 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 исключить подобный код?То есть сказать :позволит ли это мне динамически выбирать конкретную реализацию для загрузки в зависимости от типа входного параметра?

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

Это было полезно?

Решение

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

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

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

Другие советы

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

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

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

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

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

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

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

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

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

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

IoC - это больше для конфигурации?

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

1) IoC - это не что иное, как приятная экономия времени по сравнению с внедрением принципа "композиция важнее специализации / наследования".

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

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

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

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

тогда

Сервис IAmazementService = новый сервис AmazementService (интересный, вторая стратегия, третья и т.д.)

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

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

Деймон

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top