Какие преимущества дает контейнер DI по сравнению с фабрикой? - PullRequest
3 голосов
/ 09 марта 2012

Вокруг этого много дискуссий, но, похоже, никто не отвечает на этот вопрос.

В настоящее время я рассматриваю возможность использования сервисного контейнера Symfony 2 .Однако чем больше я на это смотрю, тем больше кажется, что я мог бы сделать то же самое с сервисной фабрикой.Рассмотрим следующий пример:

services.yml

services:
    my_mailer:
        class:        Acme\Mailer
        arguments:    [sendmail]
    newsletter_manager:
        class:     Acme\Newsletter\NewsletterManager
        arguments: [@my_mailer]

Теперь, чтобы получить менеджера новостной рассылки, я делаю что-то вроде:

// this has been configured with the above yml file
$serviceContainer = new ServiceContainer();
$newsletterManager = $serviceContainer->get("newsletter_manager");

Тем не менее, рассмотрим следующий код заводского стиля:

class ServiceContainer
{
    public function getMyMailer()
    {
        return new Acme\Mailer("sendmail");
    }

    public function getNewsletterManager()
    {
        return new Acme\Newsletter\NewsletterManager($this->getMyMailer());
    }
}

И затем, используя его:

$serviceContainer = new ServiceContainer();
$newsletterManager = $serviceContainer->getNewsletterManager();

Есть ли что-то, что я здесь упускаю?Потому что я не вижу преимущества использования контейнера DI, если фабрика может сделать все это для меня.

Я слышал, что использование фабрики заставляет ваш код "зависеть от фабрики".Я либо не понимаю этот аргумент, либо человек, спорящий с фабриками, растерян.Только класс верхнего уровня (корень композиции) будет иметь ссылку на фабрику, точно так же, как он будет единственным с ссылкой на контейнер DI.

1 Ответ

2 голосов
/ 09 марта 2012

Есть ли что-то, что я здесь упускаю?Потому что я не вижу преимущества использования контейнера DI, если фабрика может сделать все это для меня.

Да - вы используете свой контейнер DI с помощью Service Locator (анти-) шаблон вместо введения ваших зависимостей в ваши классы.Ваш класс вообще не должен ссылаться на ваш DI-контейнер.

Вместо этого должен быть только один агрегатный корень, в котором вы создаете контейнер и разрешаете все зависимости.После разрешения экземпляра класса верхнего уровня все его зависимости (и зависимости зависимостей и т. Д.) Затем разрешаются с использованием контейнера IoC с использованием Голливудского принципа - когда создаются экземпляры класса, все егозависимости передаются, экземпляр никогда не запрашивает саму зависимость.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...