I have always felt uncomfortable when dealing with classes that needed to instantiate a lot of objects since I've been using Dependency Injection principles.
For instance, let's say I have a class that's supposed to raise a lot of different kind of events. Each event has a different type, so what I'd do is to have a different factory for each different event type. If I have 10 events, then I'll have to have 10 factories. That doesn't seem nice. I could also have a single factory for all the different kinds of events, but that doesn't seem too right, also.
(for the C# crowd, I'm not talking about .NET's events here. This was just an example to get to the point, just think of them as regular classes!)
This was just an example. I don't have a problem in having a factory here or there, but in certain kinds of projects where one has to create lot of objects at run-time, it seems as I have to make a factory for almost every class I define!
How do you handle this situation? Am I missing something?
I've seen people just passing around a reference to the IoC Container they use, but that doesn't seem any good to me. IMO, the domain model shouldn't even know a IoC Container is being used!
Thanks
There's nothing wrong with a class that instantiates many other objects. Instead, that class should be treated as an aggregate root domain entity. As for different "types" of entity, if you assume they implement the same interface or inherit from the same base class, then passing a type
argument to Factory.create(type)
is how I usually go about approaching this issue. The internals of create()
may delegate to other classes ala the Strategy pattern, but the client facing API is straightforward.
Now if you're creating a factory for every class you're dealing with, that sounds like something of anti-pattern. Study the aggregate root pattern mentioned above and see if you can organize your entities into graphs - you should be able to - such that one factory suffices for generating the whole graph.
As for IoC, the domain model should not know about the container. When I have entities that need references to singletons - usually factories - in the container I usually inject one factory into another as such:
class FactoryA {
void setFactoryB(FactoryB factoryB) { /* sets into state */ }
EntityA create(Enum type) {
EntityA entityA = new EntityA();
/* DI FactoryB - this method is probably default access */
entityA.setFactoryB(getFactoryB());
}
}
class FactoryB {}
So in the above example both FactoryA
and FactoryB
are singletons managed by the IoC container. EntityA needs a reference to FactoryB
, so FactoryA
is injected with a reference to FactoryB
that's passed along inside the create()
method.