Comments On Composite

We've used the Composite pattern within GenomeTopographer 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 CompositeExperiment? itself pretty much just represents a data flow graph of experiments. We associate an Experiment Prototype with a composite to provide specialized behavior. --MoiraMallison
C3 has a big use of CompositePattern in its Bin and BinSupply? 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. --RonJeffries
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 CascadingCompositePattern?. 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:
  CompanyTerritoryComponent --------------------------------------+
            ^                                                     |
            |                                                     |
          +-+-----------------------+-----------------------+     |
          |                         |                       |     |
  LegalTerritoryComponent   SalesTerritoryComponent   CompanyComposite
             ^        |              ^          |
             |        |              |          |
      +------+---+    |         +----+-----+    |
      |          |    |         |          |    |
  LegalLeaf LegalComposite  SalesLeaf SalesComposite

This ensures that the top nodes are CompanyComposite?, 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 CompanyLeafs?, but adding one is trivial.

As for the inexperienced developers, I wouldn't say that DesignPatterns 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. -- JeffGrigg

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? -- RobertDiFalco

Use the Java interface mechanism. Each base class implements Composite. However, this may violate OnceAndOnlyOnce in some situations as each base class realizes its own copy of the shared composite interface. Wyatt Matthews
I once commented to KentBeck that I didn't like the "official" DesignPatterns 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 ..." --RonJeffries

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? -- RobertDiFalco

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" DesignPatterns 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. -- JeffGrigg

You should take a look at the Composite and Visitor variations I used in CppUtxOverview. 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. -- RobertDiFalco

Moving my controversy to CompositeConsideredHarmful . We'll see what happens. --RichardHenderson.

View edit of March 14, 2003 or FindPage with title or text search