Fractal Models: Extending Composite
Whenever it seems like Composite might apply, another voice pops up in your head that says ‘every time something rolls up into a parent, do we need to trot out Composite?‘ The deciding rule is really simple: do you have cases where you need to be able to have collections of both individual and group instances? For example, consider the case of the original JUnit design: Test is an interface, TestCase is an individual Case, then TestSuite is a set of TestCases.
The compulsion to make a Composite out of User/Group relationships is that Groups can often contain other groups.
The fractalization comes in when you realize that User/Group need to be extended. For example, consider Contractor/Subcontractor. We need fields of course, having to do with contracting. We can‘t stick them into User and Group. So how do we extend this?
First question: do we extend it. Is a Contractor a User? Here‘s a reality of type-safe languages: if you do go the inheritance route, you are not going to be able to leverage the collection in the base class because that‘s typed to the corresponding class (Group). If you need a collection of Contractors in the new Composite, you are kind if screwed. Now, in Objective-C, you would not have this problem because those objects would be able to respond to either set of ‘messages.‘
In Java, there are two ways to do inheritance, through interfaces and through classes. Problem is, because these are entities, the interface approach is not going to work really, which is too bad because using interfaces opens the door to multiple inheritance. Consider, for instance, a system to sell products to people with Diabetes. That person is a Customer and also a Patient. It doesn‘t make any sense to put things like which type of diabetes they have into the same interface as how they plan to purchase their products.
Ultimately, I don‘t think extending Composites works very well in Java. You end up being better off with one of two strategies: either factor out the common elements of the two hierarchies into an interface, or delegate by having an instance of the first composite inside the instance of the second.