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
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.
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.
also read:
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