I've been a zone leader with DZone since 2008, and I'm crazy about community. Every day I get to work with the best that JavaScript, HTML5, Android and iOS has to offer, creating apps that truly make at difference, as principal front-end architect at Avego. James is a DZone Zone Leader and has posted 639 posts at DZone. You can read more from them at their website. View Full User Profile

Design Patterns Uncovered: The Composite Pattern

05.17.2010
| 25668 views |
  • submit to reddit

Today's pattern is the Composite pattern, which comes into play when developing a system where a component could either be an individual object or a representation of a collection of objects. 

Composite in the Real World 

In programming, composites are used when dealing with tree structures. This itself is quite an abstract concept. One example of composite that you see daily is a menu system, where a menu bar has menu has many menu items, which themselves can have submenus. Anything that can be modelled as a tree structure can be considered an example of Composite, such as an organization chart.

Design Patterns Refcard
For a great overview of the most popular design patterns, DZone's Design Patterns Refcard is the best place to start. 

The Composite Pattern

The Composite is known as a structural pattern, as it's used to form large object structures across many disparate objects. The definition of Composite provided in the original Gang of Four book on Design Patterns states: 

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

 

In it's simplest form, we can think of a composite as a collection of objects, where any one of these objects could itself be a composite, or a simple object. Let's take a look at the diagram definition before we go into more detail.

The Component interface defines the interface that all objects in the composed system need to use, whether they are leafs (simple objects) or compositions. However, this is usually implemented as an abstract class providing some default behaviour for the add, remove and getChild methods.

The Leaf has no children, and as such only needs to implement the operation method. The Composite needs to do more, as it also contains components. The composite will more than likely need to implement the operation method, which is considered as a Leaf-related operation. Sometimes this may not make sense for a composite to implement.  Usually, the Composite will implement methods by delegating to the children. The Client simply uses the Component  interface to manipulate the objects.

Would I Use This Pattern?

This pattern should be used when you want to represent objects in a hierachical fashion, or you need objects and composites to be treated uniformly. 

Graphics frameworks are the most common use of this pattern.  The base Graphic object provides the base class for all other graphic objects, such as Line, Rectangle, which provide their own implementations of the paint()/draw() method. The Composite pattern is frequently used for abstract syntax tree representations. 

So How Does It Work In Java?

Graphics is a great example of how the Composite pattern works, so I'll use that here. First, we create an general interface for our graphics object. The main thing is that we have a paint method.  Each graphic could be composed of other graphics too, so we'll need to provide a way to contain these objects. 

//Component interface 
public interface Graphic
{
public void add(Graphic g);
public void remove(Graphic g);
public Graphic get(int index);
public void paint();
}

Next, we'll implement this interface for CompositeGraphic objects. The key point to note here is that it's paint method delegates the painting to children objects: 

//Composite 
public class CompositeGraphic implements Graphic
{
private List<Graphic> children = new ArrayList<Graphic>();

public void paint()
{
//run the paint operation for each child
for(Graphic g: children)
{
g.paint();
}
}


public void add(Graphic g)
{
children.add(g);
}

public void remove(Graphic g)
{
if(children.contains(g))
{
children.remove(g);
}
}

public Graphic get(int index)
{
if(index < children.size())
{
return children.get(index);
}
}


}

The leaf, in this case SimpleGraphic, cannot contain other graphics, so it doesn't need to implement the list operations. The most important this is that it provides a concrete implementation of the paint() method: 

//Leaf
public class SimpleGraphic implements Graphic
{

public void paint()
{
//run the paint operation
}

/**
* Because we have no children, these operations will do nothing
**/
public void add(Graphic g)
{
//unsupported operation
}

public void remove(Graphic g)
{
//unsupported operation
}

public void get(int index)
{
//unsupported operation
}
}

And finally, for the client, things couldn't be easier. All they need to do is to know about the interface, and all the work is done for them: 

//Client.
public class GraphicsClient
{
/**
* Given a graphics context, client can just call paint, without worrying if this is a composite or leaf
**/
public void paint(Graphics g)
{
g.paint();
}
}

Watch Out for the Downsides

The Composite pattern does one thing really well, and that is that it allows you to treat both nodes and leafs in the same way. However, by providing this flexibility and transparency, you're choosing a trade-off on the Single Responsibility principle.  This is not necessarily a bad thing, but it's something that you should keep in mind. 

Your system could also be overly general, and it can be difficult to find objects. Taking this into account, the pattern probably isn't ideal to use as a data structure. In cases where the ordering of child nodes is important, you will need to add in extra functionality, perhaps utilizing the Iterator pattern. 

Other Articles in This Series
The Observer Pattern
The Adapter Pattern
The Facade Pattern
The Factory Method Pattern
The Abstract Factory Pattern
The Singleton Pattern
The Strategy Pattern
The Visitor Pattern

The Decorator Pattern
The Proxy Pattern
The Command Pattern
The Chain of Responsibility Pattern
The Interpreter Pattern

Next Up

In the next article, I'll introduce the Flyweight design pattern.
Tags:

Comments

Gervais Blaise replied on Tue, 2010/05/18 - 1:57am

Hum, in my opinion this is not a good pattern because he add unuseds methods on our objects. In your example, the SimpleGraphic object will realize four methods and only one of them will be used. Also, this pattern add to your "domain" objects the tree structure aspect who will be bad if this aspect is required in only one view. So this pattern can be better when he is coupled with the decorator pattern because we avoid the inheritence weakness.

James Sugrue replied on Tue, 2010/05/18 - 3:55am

You raise a good point. It seems that Composite usually works best when pair with other patterns.

Mladen Girazovski replied on Tue, 2010/05/18 - 5:48am

Hum, in my opinion this is not a good pattern because he add unuseds methods on our objects. In your example, the SimpleGraphic object will realize four methods and only one of them will be used. 

 Well, this is the "price" you have to pay for a common interface.

 

 Also, this pattern add to your "domain" objects the tree structure aspect who will be bad if this aspect is required in only one view.

 Well, imho it is an design flaw if you make a domain object an composite, but its not supposed to be or doesn't fit the structure.

 I use Composite a lot, and most GUI Frameworks also (SWT for instance), of course it has to fit, you  cannot just apply patterns in situations where they don't fit and pretend that its a good thing.

Mohamed El-beltagy replied on Tue, 2010/05/18 - 9:46am

I used the composite pattern in a project where I have a single objct that is composed of multiple domain objects. The client only invokes my composite object and it internaly manages calling the composed domain objects and managing their integrity with relation to each other. All transparent to the client.

I think that was a very good advantage.

I totally agree with Mladen.

In other words, it's not the importance of mastering a pattern, but it's the importance of mastering when to use a pattern.

 

prashant.jalasutram replied on Fri, 2010/05/21 - 8:47am

nice article. Thanks Prashant http://prasanthaboutjava.blogspot.com/

Comment viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.