We've used the Composite pattern within Genome Topographer for the Experiment hierarchy. Experiments have inputs, conditions and outputs. They also know how to compute themselves. An atomic experiment is one step in an experimental protocol. The composite experiments hold multiple atomic experiments, which may execute in sequence or in parallel depending on how they are linked together. We're thinking about iterative and conditional links within the composite, as well.
The Composite pattern worked well for this application. Our biggest challenge has been to remember to not assume that we always have a composite --- that is, to maintain the common interface.
The Composite Experiment itself pretty much just represents a data flow graph of experiments. We associate an Experiment Prototype with a composite to provide specialized behavior. --Moira Mallison
C3 has a big use of Composite Pattern in its Bin and Bin Supply objects. It's a nice compact way to do the single/group thing. However, IMO it is rather deep in the bag of tricks and can be tricky to implement. Use when really needed, with caution. --Ron Jeffries
Composite as a nickname for the idea saved us in several really heated discussions. Someone just said, "that's a composite", and the rest said, "oh. yeah." and that was that.
OTOH, Composite caused quite some trouble with the following design problem: company has legal and sales territories. the top-level legal territories are the same as the top-level sales territories, but after that, they go their own ways, but the trees are always nicely triangular in shape. Certain properties and behaviors attach to the top levels, the middle levels, and the leaf levels in each. The composite pattern does not cope with this top, middle, bottom stuff. OMT (and UML?) couldn't handle the polymorphism. So we used the general idea of Composite, but not the thing written in the book. Each person who joined the project said, "That's wrong. That's not what's in the book." And long, tedious arguments would follow for days until they got that what is in the book does not always work. ugh.
I saw an article in C++ Journal describing Cascading Composite Pattern. The idea is that the leaves of your composite tree can also be instances of the composite pattern. In other words, you apply the pattern recursively.
To make this concrete, here's how to do the territories:
C''''''ompanyTerritoryComponent --------------------------------------+ ^ | | | +-+-----------------------+-----------------------+ | | | | | L''''''egalTerritoryComponent S''''''alesTerritoryComponent C''''''ompanyComposite ^ | ^ | | | | | +------+---+ | +----+-----+ | | | | | | | L''''''egalLeaf L''''''egalComposite S''''''alesLeaf S''''''alesComposite
This ensures that the top nodes are Company Composite, the shared Legal and Sales territories, and that once you get to a Legal or Sales territory, everything under it will be of the same type. I've assumed that there are no Company Leafs, but adding one is trivial.
As for the inexperienced developers, I wouldn't say that Design Patterns is "wrong;" it's only inapplicable to this situation. And anyway, you're supposed to modify the design patterns to fit your situation during implementation. They're patterns, not a code library. -- Jeff Grigg
Jeff, I'm not sure I get this. The problem is that while your component and composites share type, and your components are all a kind of component, you composites are not a kind of composite. This makes it hard to create a Generic Visitor that simply visits Component or Composite. Of course, the book doesn't handle this either. That is one of the problems with the composite pattern. It cannot be provide in Java or Smalltalk as an extensible ADT. Each time you use it you must recreate the class hierarchy (except for the component). Any thoughts on this? -- Robert Di Falco
Use the Java interface mechanism. Each base class implements Composite. However, this may violate Once And Only Once in some situations as each base class realizes its own copy of the shared composite interface. Wyatt Matthews
I once commented to Kent Beck that I didn't like the "official" Design Patterns way of doing composite. He replied, as only he can, "Well, you're much smarter than I am. You can do it that way if you want to ..." --Ron Jeffries
Okay, Ron, don't leave us guessing. How do you like doing it? More like just another Collection Type (i.e. Abstract Data Type) something like a Tree or Graph? Or using another method alltogether? -- Robert Di Falco
I tend to favor using C++ pure virtual functions in the base classes, as it enables compile-time enforcement of the requirement that child classes implement certain methods. This deviates from the "official" Design Patterns description, which recommends 'implementing (appropriate) default behavior' in the "Component" base class. I usually add another abstract base class between Component and the Leaf classes, to hold state and behavior that is common to all Leaf classes but different from the Composite class. I consider these minor implementation variations, rather than heretical deviations from the faith. Others, I'm sure ;->, would be more than glad to argue.
-- Jeff Grigg
You should take a look at the Composite and Visitor variations I used in Cpp Utx Overview. These allow you to get rid of the virtual functions altogether by trusting the dynamic dispatching done by the Visitor. All the base class (i.e. Component) really needs is the visitor acceptor. -- Robert Di Falco
Moving my controversy to Composite Considered Harmful . We'll see what happens. --Richard Henderson.
See original on c2.com