Фабрика против PicoContainer - Преимущества контейнеров IoC - PullRequest
2 голосов
/ 02 июня 2011

Я пытаюсь открыть свой разум для причудливого IoC принципа, и я наткнулся на статью: Мартин Фаулер на IoC

Он приводит несколько примеров использования PicoContainer :

private MutablePicoContainer configureContainer() {
        MutablePicoContainer pico = new DefaultPicoContainer();
        Parameter[] finderParams =  {new ConstantParameter("movies1.txt")};
        pico.registerComponentImplementation(MovieFinder.class, ColonMovieFinder.class, finderParams);
        pico.registerComponentImplementation(MovieLister.class);
        return pico;
    }

, а затем пример использования:

public void testWithPico() {
        MutablePicoContainer pico = configureContainer();
        MovieLister lister = (MovieLister) pico.getComponentInstance(MovieLister.class);
        Movie[] movies = lister.moviesDirectedBy("Sergio Leone");
        assertEquals("Once Upon a Time in the West", movies[0].getTitle());
    }

И первая мысль, которая пришла мне в голову: зачем использовать что-то столь сложное, как PicoContainer, для настройки создания объекта - и фактически применять Dependency Injection - (я - разработчик .NET, поэтому в .NET это, вероятно, потребует используя Reflection (что занимает много времени), когда мы можем достичь той же инкапсуляции создания объекта в (например) Фабриках или Builder , с быстрым новый оператор.

Еще одна вещь: configureContainer () все еще компилируется, точные типы указываются во время компиляции. Так почему бы не использовать фабрики и решить в конфигурационном файле, какую фабрику использовать?

Поскольку я новичок в этом подходе, думаю, что-то упускаю из-за преимуществ Контейнеров IoC.

1 Ответ

1 голос
/ 03 июня 2011

Я только что обновил ответ по этому вопросу здесь .

В .Net я бы посмотрел документацию по Unity Framework (от MSFT). Я также остерегался идеи жесткого кодирования регистраций реализации, но со временем мне это удалось. Главным образом потому, что вы действительно можете использовать конфигурацию на основе файлов, вы можете зарегистрировать более одной реализации (и пометить каждую из них так, чтобы их можно было вызывать), и обычно вы в любом случае не используете более одной реализации в рабочей среде.

Самым большим преимуществом является автоматическое подключение - там, где ваши зависимости находятся для вас. Цепная автоматическая разводка сложного набора классов очень изящна, если не сказать больше, потому что вы можете легко зарегистрировать экземпляр Mock одного из 10 рассматриваемых классов, не касаясь кода реализации. Это приводит к огромному количеству тестируемости за счет начальной загрузки контейнера. Для меня в наши дни это настольные ставки, даже не стоит обсуждения. Представьте себе, если Тип 1 зависит от 2, 3 и 4, 4 зависит от 5 и 6, 6 зависит от 7. Если я хочу проверить, как система реагирует на ошибку в 6, как бы я это сделал? Все, что мне нужно сделать, это Mock (используя классную среду, такую ​​как Moq) Type6, зарегистрировать mock, но использовать реальные реализации для других классов.

[Fact]
public void TestType6BlowingUp()
{
  IocContainer container = new IocContainer();
  container.RegisterType(Type1, Type1Impl);
  container.RegisterType(Type2, Type2Impl);
  container.RegisterType(Type3, Type3Impl);
  container.RegisterType(Type4, Type4Impl);
  container.RegisterType(Type5, Type5Impl);
  container.RegisterType(Type6, Type6Mock);
  container.RegisterType(Type7, Type7Impl);

  Type1 type1 = container.Resolve<Type1>();
  Type1Response response = type1.DoSomethingThatCallsType6Downstream();
  //Should get errorcode 500
  Assert.True("Expected ErrorCode 500", response.ErrorCode == 500);
}
...