Advertisment

Composite Pattern

author-image
CIOL Bureau
Updated On
New Update

Avijeet Dash & Satyabrata Dash

Advertisment

Intent

Advertisment

Compose objects into tree structures to represent part-whole family

hierarchies. This pattern lets clients treat individual and compositions of

object uniformly.

In 30 Seconds

Advertisment

The catch is "achieving recursive composition by using a tree structure

which makes the client simple". A composite is a collection of objects.

Each object contains either a composite or a primitive object and the Composite

object represents a tree hierarchy with each object representing a node on it. A

node may have a branch i.e. another composite or it may just be a primitive

object. The key to the composite pattern is an abstract class that represents

both the primitives and their containers. This abstract class called ‘component’

declares all common operations for both composite and primitive (leaf nodes)

objects as well as all the child management operations. So client code

manipulates objects in the composition through the component interface.

Advertisment

Motivation

A primitive node doesn’t have any children where as a composite node has

children. In a simple example a composite node will return an Enumeration of

child nodes where as a primitive node will return nothing while trying to

retrieve the child nodes. So one group of thought suggests treating both of them

differently and keeping two interfaces. But Composite pattern insists on

retaining a uniform interface. So this makes the client simple. The client is

ignorant about the node structure and treats all the nodes in the same way. It

also makes it easier to add new components without worrying about their type.

Advertisment

Structure

Advertisment
Click here https://www.ciol.com/images/composite_pattern.gif

to view diagram

Sample Code

Advertisment

/*

Various participants in this sample code are Acomponent, Leaf, Composite and

Client. Acomponent is the Component that defines the interface for objects in

composition. It also gives a default implementation for the child components.

Leaf has no children and here any attempt to add or remove a child from Leaf

will invoke Processsing Exception.

Composite represents a child node that can have branch nodes.

*/

Example-

import java.util.*;

// Processing Exception class

class ProcessingException extends Exception{

ProcessingException(){

super();

}

}

// Component

abstract class Acomponent{

Enumeration enum;

Vector vec;

Acomponent(){

vec=new Vector();

}

public void add(Object obj) throws ProcessingException{

vec.add(obj);

}

public void remove(Object obj) throws ProcessingException{

vec.remove(obj);

}

public Object getChild(int i) throws ProcessingException{

return vec.elementAt(i);

}

public Enumeration getChild(){

System.out.println(vec);

return vec.elements();

}

}

class Leaf extends Acomponent{

public void add(Object obj) throws ProcessingException{

throw new ProcessingException();

}

public void remove(Object obj) throws ProcessingException{

throw new ProcessingException();

}

public Object getChild(int i) throws ProcessingException{

throw new ProcessingException();

}

}

class Composite extends Acomponent{

//uses parent class operations

}

public class Client{

public static void main(String args<>) throws ProcessingException{

System.out.println("An example of Composite pattern");

Acomponent com=new Acomponent();

/* Write code to add a Composite object here.

*/

//Add child nodes

com.add(new Integer(1));

com.getChild();

com.add(new Integer(2));

com.getChild();

}

}

Complexities simplified

Explicit parent reference

Storing the parent component reference in a child simplifies the traversal

and management of a composite structure. It makes it easy to move up the

structure and deleting a component.

Where should the methods be defined?

It’s a long discussed and debatable topic. Should the methods be declared

in the Component class and let Composite and Leaf inherit them? But the critics

of this idea feel that Leaf unnecessarily inherits operation that is never meant

for it. It also involves a trade-off between safety and transparency. If we

define the operations in the Component class, then the same interface holds good

for both Leaf and Composite subclasses. It also gives transparency, because the

client needn’t bother about Leaf or Composite class. But if we define the

operations at a subclass level that gives more safety as any attempt to invoke

illegal operations can be caught during compile time.

So all these issues must be considered specific to an application.

Caching child information

When it is required to traverse the tree frequently to know about the

children, it’s better to cache them in the Composite class. It will improve

the performance a lot. We can also define a listener that will automatically

refresh the cache, when there is any update in the tree.

Choose a data structure to store components

We can choose a data structure out of many available in Java Collection API

like ArrayList, HashMap, Hashtable, LinkedList, Vector etc. Choosing a

particular data structure depends on requirement like efficiency, safety etc.

Vector and Hashtable are both thread-safe and hence slower in execution unlike

ArrayList or HashMap.

Also Known as and Related Patterns

The related patterns are Chain of Responsibility, Decorator, Flyweight,

Iterator and Visitor pattern.

The Chain of Responsibility pattern can be combined with the Composite

pattern by adding child to parent links so that children can get information

from an ancestor without having to know which ancestor the information came

from.

When Decorator is used with Composite, they have a common parent class. So

decorators will have to support the Component interface with common operations.

Flyweight also allows to share components but they don’t maintain a

reference to their parents.

We can use Iterator to traverse the tree in Composite.

Visitor encapsulates operations in a single class that would otherwise be

spread across multiple classes.

(The authors are senior developers at MindTree Consulting. They can

be reached at avijeetd@mindtree.com

and satyabrata_dash@mindtree.com
).

tech-news