Composite Pattern – Structural Design Patterns in Java

Composite Pattern is to compose set of objects into tree structure to represent a part of hierarchies. This structure for clients is a single unit uniformly. In software engineering, the composite pattern come under the structural design pattern of 23 GoF Design Pattern, according to this pattern, a group of same type of objects treated as single object by client.

The Composite Pattern

According to the Gang of Four:

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

Spring 5 Design Pattern Book

You could purchase my Spring 5 book that is with title name “Spring 5 Design Pattern“. This book is available on the Amazon and Packt publisher website. Learn various design patterns and best practices in Spring 5 and use them to solve common design problems. You could use author discount to purchase this book by using code- “AUTHDIS40“.
Spring-5-Design-Pattern

Motivation behind the Composite Design pattern is that objects grouped into Tree Structure, this structure actually is combination of the Node-Leaf and Branches. In tree structure, Nodes have the number of leaves and another nodes and Leaf doesn’t has anything, no child of leaf, so leaf treated as end point of tree structured data.

UML Class Diagram for Composite Design Pattern

Let’s see the following UML class diagram for this pattern.

Composite Pattern Design Patterns in Java

Let’s have a look into following terms used in this design pattern.

Component

  • It is basically branch of tree and branch has another branches, nodes and leaves, component provides the abstraction for all components, including composite.
  • In the composition pattern, component basically declares as an interface for objects.

Leaf

  • It is an object which implements all Component methods

Composite

  • Composite component represents as a node in the tree structure, it have another nodes and leaves, it represents a composite Component.
  • It has methods to add the children, i.e. it represents collection of same type of objects.
  • This component has another component methods for its children.

Benefits of Composite Pattern

  • This pattern provide the flexibility to add new component to process dynamically with change in the existing components.
  • This pattern allows you to create a class hierarchies that contains individual and composite objects.

Applicability

This pattern we can use to solve following common problems:

  • As a developer, It is more difficult to design an application such as the client access your objects uniformly across the application, no matter that object was compositions of objects or was individual object. This design pattern resolve difficulties and allows you to design object such a way, you could use that object as a compositions of objects and single individual object.
  • This pattern solve the challenge faced in creating the hierarchical tree structures to provide clients a uniform way to access and manipulate objects of the tree. The composite pattern is a good choice; it is less complex in this situation to treat primitives and composites as homogeneous.

Example Sample Implementation of Composite Design Pattern

In this real-world example, we demonstrate the Composite pattern used in building a graphical tree structure made up of primitive nodes (lines, circles, etc) and composite nodes (groups of drawing elements that make up more complex elements).

Step 1: Create DrawingElement class.
DrawingElement.java

/**
 * 
 */
package com.doj.patterns.structural.composite;

/**
 * @author Dinesh.Rajput
 *
 */
public abstract class DrawingElement {
	
	protected String name;

	// Constructor
	public DrawingElement(String name){
		this.name = name;
    }

	public abstract void add(DrawingElement d);

    public abstract void remove(DrawingElement d);

    public abstract void display(int indent);
}

Step 2: Create PrimitiveElement class.
PrimitiveElement.java

/**
 * 
 */
package com.doj.patterns.structural.composite;

/**
 * @author Dinesh.Rajput
 *
 */
public class PrimitiveElement extends DrawingElement {

	public PrimitiveElement(String name) {
		super(name);
	}

	@Override
	public void add(DrawingElement d) {
		System.out.println("Cannot add to a PrimitiveElement");
	}

	@Override
	public void remove(DrawingElement d) {
		System.out.println("Cannot remove from a PrimitiveElement");
	}

	@Override
	public void display(int indent) {
		System.out.println(indent + "-" + name);
	}

}

Step 3: Create CompositeElement class having list of DrawingElement objects.
CompositeElement .java

/**
 * 
 */
package com.doj.patterns.structural.composite;

import java.util.ArrayList;
import java.util.List;

/**
 * @author Dinesh.Rajput
 *
 */
public class CompositeElement extends DrawingElement {
	
	private List elements = new ArrayList<>();

	public CompositeElement(String name) {
		super(name);
	}

	@Override
	public void add(DrawingElement d) {
		elements.add(d);
	}

	@Override
	public void remove(DrawingElement d) {
		elements.remove(d);
	}

	@Override
	public void display(int indent) {
		System.out.println("----"+ name+"----");
		// Display each child element on this node
		for(DrawingElement d : elements){
			d.display(indent + 2);
		}
	}

}

Step 4: Use the DrawingElement class to create and print DrawingElement hierarchy.
CompositePatternDemo.java

/**
 * 
 */
package com.doj.patterns.structural.composite;

/**
 * @author Dinesh.Rajput
 *
 */
public class CompositePatternDemo {

	/**
	 * @param args
	 */
	public static void main(String[] args) {
		// Create a tree structure 
		CompositeElement root = new CompositeElement("Picture");
		root.add(new PrimitiveElement("Red Line"));
		root.add(new PrimitiveElement("Blue Circle"));
		root.add(new PrimitiveElement("Green Box"));

		// Create a branch
		CompositeElement comp = new CompositeElement("Two Circles");
		comp.add(new PrimitiveElement("Black Circle"));
		comp.add(new PrimitiveElement("White Circle"));
		root.add(comp);

		// Add and remove a PrimitiveElement
		PrimitiveElement pe = new PrimitiveElement("Yellow Line");
		root.add(pe);
		root.remove(pe);

		// Recursively display nodes
	      root.display(1);
	}
}

Step 5: Let’s run the above demo class and verify the output.

----Picture----
3-Red Line
3-Blue Circle
3-Green Box
----Two Circles----
5-Black Circle
5-White Circle

Previous
Next