Reputation: 66851
There are many discussions around here about this, but none seem to really answer the question.
I'm currently considering using the Symfony 2 service container. The more I look at it though, the more it seems like I could just do the same thing with a service factory. Consider the following example:
services.yml
services:
my_mailer:
class: Acme\Mailer
arguments: [sendmail]
newsletter_manager:
class: Acme\Newsletter\NewsletterManager
arguments: [@my_mailer]
Now to get a newsletter manager, I do something like:
// this has been configured with the above yml file
$serviceContainer = new ServiceContainer();
$newsletterManager = $serviceContainer->get("newsletter_manager");
However, consider the following factory style code:
class ServiceContainer
{
public function getMyMailer()
{
return new Acme\Mailer("sendmail");
}
public function getNewsletterManager()
{
return new Acme\Newsletter\NewsletterManager($this->getMyMailer());
}
}
And then using it:
$serviceContainer = new ServiceContainer();
$newsletterManager = $serviceContainer->getNewsletterManager();
Is there something I'm missing here? Because I don't really see the advantage to using a DI container if a factory can do all of that for me.
I have heard using factories causes your code to "depend on the factory". I either don't understand this argument or the person arguing against factories is confused. Only the top level class (the composition root) would have a reference to the factory, just like it would be the only one with the reference to the DI container.
Upvotes: 3
Views: 223
Reputation: 160922
Is there something I'm missing here? Because I don't really see the advantage to using a DI container if a factory can do all of that for me.
Yes - you are using your DI container using the Service Locator (anti-)pattern instead of injecting your dependencies into your classes. Your class should not have to reference your DI container at all.
Instead there should be just a single aggregate root where you create the container and resolve all dependencies. Once you have resolved your top level class instance all of its dependencies (and the dependencies of the dependencies and so on) are then resolved using the IoC container using the Hollywood Principle - when class instances are created all of its dependencies are passed in, the instance never asks for a dependency itself.
Upvotes: 2