Wizard API updated!
Tim Boudreau has released a new version of the Swing Wizard library (version 0.997) that fixes the WizardException bug reported in JavaWorld's recent Open Source Java Project profile. The article's examples have been reworked to test out the new, improved WizardException. Thanks, Tim, for this helpful fix!
Open Source Java Projects: The Wizard API

Newsletter sign-up

Sign up for our technology specific newsletters.

Enterprise Java
View all newsletters

Email Address:

A look at the Composite design pattern

Treat primitive and composite objects the same way

The other day I was listening to National Public Radio's Car Talk, a popular weekly broadcast during which callers ask questions about their vehicles. Before every program break, the show's hosts ask callers to dial 1-800-CAR-TALK, which corresponds to 1-800-227-8255. Of course, the former proves much easier to remember than the latter, in part because the words "CAR TALK" are a composite: two words that represent seven digits. Humans generally find it easier to deal with composites, rather than their individual components. Likewise, when you develop object-oriented software, it's often convenient to manipulate composites just like you manipulate individual components. That premise represents the fundamental principle of the Composite design pattern, the topic of this Java Design Patterns installment.

The Composite pattern

Before we dive into the Composite pattern, I must first define composite objects: objects that contain other objects; for example, a drawing may be composed of graphic primitives, such as lines, circles, rectangles, text, and so on.

Java developers need the Composite pattern because we often must manipulate composites exactly the same way we manipulate primitive objects. For example, graphic primitives such as lines or text must be drawn, moved, and resized. But we also want to perform the same operation on composites, such as drawings, that are composed of those primitives. Ideally, we'd like to perform operations on both primitive objects and composites in exactly the same manner, without distinguishing between the two. If we must distinguish between primitive objects and composites to perform the same operations on those two types of objects, our code would become more complex and more difficult to implement, maintain, and extend.

In Design Patterns, the authors describe the Composite pattern like this:

Compose objects into tree structures to represent part-whole hierarchies. Composite lets clients treat individual objects and compositions of objects uniformly.


Implementing the Composite pattern is easy. Composite classes extend a base class that represents primitive objects. Figure 1 shows a class diagram that illustrates the Composite pattern's structure.

Figure 1. A Composite pattern class diagram



In Figure 1's class diagram, I used class names from Design Pattern's Composite pattern discussion: Component represents a base class (or possibly an interface) for primitive objects, and Composite represents a composite class. For example, the Component class might represent a base class for graphic primitives, whereas the Composite class might represent a Drawing class. Figure 1's Leaf class represents a concrete primitive object; for example, a Line class or a Text class. The Operation1() and Operation2() methods represent domain-specific methods implemented by both the Component and Composite classes.

The Composite class maintains a collection of components. Typically, Composite methods are implemented by iterating over that collection and invoking the appropriate method for each Component in the collection. For example, a Drawing class might implement its draw() method like this:

1 | 2 | 3 | 4 | 5 | 6 | 7 |  Next >
Resources