Reputation: 481
We have to implement a factory able to create several complex objects. How should we handle it with dependency injection ?
I already read many topics about it in stackoverflow (and elsewhere), particularly the ones of Mark Seemann but can't take any decision so need your opinion.
For example:
<?php
class EventFactory
{
public function createEvent($type)
{
switch ($type) {
case 'upload':
return new UploadEvent(new FtpUploader(), new Mailer());
case 'download':
return new DownloadEvent(new FtpDownloader(), new Mailer());
case 'save':
return new SaveEvent(new EventDbModel());
case 'load':
return new LoadEvent(new EventDbModel());
case 'notify':
return new NotifyEvent(new HttpRequester());
}
}
}
I found some solutions but don't know which one to choose.
Problems: The same ones as not using depency injection.
Problems: There will be a lot of parameters in the constructors and the list can grow up
Problems: Is the role of the builder DP to handle dependencies? I'm afraid to get the same issues as solution #1.
What should we do ?
Ben
Upvotes: 1
Views: 148
Reputation: 32936
Personally I would go with option 2. Builders are usually used when you want to configure the building but hide the implementation from the client. When you only have to pass the parameters then a factory is usually better.
If you are worried about the number of parameters then you could either pass a parameter object to the factory, or produce single responsibility factories which each know the type of thing they create and how to create it and then assemble them into a chain of responsibility, asking each one if it can create the requested type and passing it along if it can't, or even just a simple list of 'single type factory' instances.
That way each 'factory' only has the dependencies it needs, and the chain simply orchestrates the available factories and so only needs dependencies on them, knowing nothing about what dependencies they have.
Not using the chain of responsibility is simpler. Some solution like this:
public class EventFactory
{
IEnumerable<ISingleTypeEventFactory> factories
public EventFactory(IEnumerable<ISingleTypeEventFactory> factories)
{
this.factories = factories;
}
public Event CreateEvent($type)
{
foreach(factory in factories)
{
if (factory.CanHandleType($type))
{
return factory.CreateEvent($type);
}
}
}
}
Upvotes: 3