views:

134

answers:

3

I have a problem that involves a relatively large object hierarchy as follows:

  • game has one community manager
  • community manager has one network
  • network has many players
  • network has many friendships
  • player has one strategy manager
  • player has one memory
  • player has one neighbourhood
  • neighbourhood has many players
  • strategy manager has many strategies

As you can see, the hierarchy is relatively complex and in at least one place cyclic (network has many agents having one neighbourhood which has one network). At the moment I am using a static construct method on a GameFactory class to construct the whole hierarchy but I'm pretty sure this is the least flexible way of doing it!

In terms of building a complex hierarchy of objects what is the best pattern to use? I've read up on the Factory Method, Abstract Factory and Builder patterns and I think one of the factory patterns is suitable but I don't really know how to apply it to such a complex hierarchy?

As I see it I'll need many factories for each part of the system but this will result in a collection of factory classes mirroring the model classes.


Edit: It has become clear from the discussion in suggestions given so far that I should have explained more about why I require factories to build my object hierarchies rather than allowing constructors themselves to build their dependencies.

This is because I am using dependency injection to aid in test driven development. I'm taking a mockist approach to the testing which requires the ability to inject mocks representing an object's dependencies and as such I have to avoid using new in any constructors.

From the suggestions given so far it seems there are a number of possible ways of doing this:

  • Create a secondary constructor in each class that builds any dependencies required by the object being constructed. This allows dependency injection and simple object hierarchy construction.
  • Have a factory class (either a single one or a hierarchy of them depending on the type of factory pattern used) mapping to each domain class to deal with its construction.
  • Use a combination of these methods where factory classes are only created when there is something that varies in the construction process (i.e., different subclasses need to be constructed under certain circumstances)

I am inclined to take the last route. What is the consensus on the best approach to take in this situation?


Edit: I'm revoking the current answer (the one by Patrick Karcher) since now that this question's focus has been clarified, none of the suggestions are complete answers.

+2  A: 

If nothing varies, ie. if your construction process is fixed, I would recommend the simplest way : have the objects themselves take care of building their dependent objects, and establishing links (potentially bi-directional).

Example : For a parent object with a collection of children, the parent can have a addChild method that ensure the coherence of the bi-directional relationship :

  1. get the previous parent of the child ; if not null, remove the child from that old parent.
  2. change the parent field in the child to the new parent
  3. add the child to the collection of children of the new parent.

If something varies, like subclasses than should be used in some context, then you have to define exactly what varies. Only after you found your precise need, the correct patterns may appear. :-)

We could help with the last part, but you are the only one that can give the required information... ;-)

KLE
+1 there is no good answer to such a general question.
peterchen
As just said to Patrick, I in fact require dependency injection which is why I was taking the factory route. Sorry, I should have made that clear in my initial post. Separate from that some of the domain classes do vary, specifically the players. Each player has a method of choosing an outcome in the game and currently I have a hierarchy of player classes. Does that mean I should have a factory to handle generating players and let a constructor handle the other entities? I'm also not sure where the dependency injection fits in here...
tobyclemson
@toby ok. Do you think you will update your question with this requisite, to give some context to readers, and explain why a solution is chosen?
KLE
@KLE updated as you asked.
tobyclemson
+3  A: 

It's important to understand why exactly you need a factory. As with a lot of "good" practices, a factory can yield certain advantages, which you sometimes want, and which you get only by using them properly.

Often the factory is another class in your object model. For example, you'll often end up with a player because you have a neighborhood with a players collection and you'll iterating through it, doing stuff to the players. Or you're starting with a network object. Or (I'm guessing) you already have a player from it you get a friendship and you get the player from it. So a friendship is factory for player objects and a player is factory for friendship objects!

You do though sometimes have reason for non-domain, dedicated factory objects. You might have a factory class as a starting point for objects that you'll begin your logic with. Often they're used when there are a lot of tricky ways some of your objects need to be instantiated and the factory is a good way to organize them. Sometimes your objects need to get instantiated with, for example, a data layer and a user and a context, and a factory can maintain those things, make your objects, and save you from having to repeat yourself in a lot of different constructors. Sometimes the factory can automatically generate common references that your various tools need.

There is one use of a factory that is growing rapidly in popularity, and deserves special mention. This is the use of a factory class to add a layer of misdirection to inject dependencies, particularly for unit testing.

My advice is if you don't have a specific reason to use a factory object in mind, don't worry about them. Just build your objects with good constructors. Then it will be natural to add properties that return related objects; these will be your first factories. This might be a good example of how you don't want to worry about design patterns at first; design patterns do not deliver success. You do. Patterns, like the various factory patterns, can help but must not replace basic object-oriented thinking.

Do you have specific reasons in mind for why you need dedicated factory objects?

Patrick Karcher
I didn't think it was related before but, yes, I'm using dependency injection throughout the hierarchy of models because I'm trying to use behaviour driven development with a mockist approach throughout. Injecting the mocks requires dependency inject as far as I understand.I suppose then the question is whether to have two constructors, one for dependency injection and another for the object constructing its own dependencies or whether to use a factory to generate and provide the dependencies. Is the former a common approach? I am more inclined towards the latter.
tobyclemson
Every option you mention cab be used well. I prefer constructors, and further when I can I like to have one constructor (or if multiple constructors, then the dependency is injected the same way.) Most of my objects are made by "factories" (which usually are other business objects) that construct and return these objects using the constructor, but the constructor makes the object self-contained. This has the substantial advantage of helping the classes to be truly black boxes.
Patrick Karcher
In my current project, all of my classes that do data access are constructed with a data object. The page creates it for me automatically and places it my user-context object, which is the starting point for most of my other objects. In an entire page, I'll often never actually inject it myself, because I have a large chain of objects creating other objects. The injection is kindof nice in production (it pools connections nicely) but in testing it's awesome. And because it in the constructor, even though it's usually manufactured anyway, I have complete **unit-level** control. I like it.
Patrick Karcher
+2  A: 

KLE is right about handling it differently depending on how static the relationships are. I'd add that it is typical for Factory classes to mirror the object model. An easy way to think of them as intelligent object that know how to connect the different classes of your model.

Kelly French
Is this something done commonly though - it seems quite bloated to have a factory class hierarchy for each domain class?
tobyclemson
It is pretty common. The alternative is for objects to have more intelligence which then causes a different sort of bloat. The best example is expecting a Circle object to know how to paint itself. It quickly causes classes to become responsible for all interactions like serialization or morphing. Such code quickly dwarfs the initial focus of the class. Better to focus such behavior in separate classes. In the end, using factories and the like are a tool to help you maintain your codes desired level of coupling and cohesiveness.
Kelly French