Composite Design Pattern

The Composite design pattern is a structural pattern that allows you to compose objects into tree structures and then work with these structures as if they were individual objects. In other words, it lets you treat individual objects and groups of objects in a uniform way. In this article, we will discuss the Composite pattern in detail, including its implementation and practical use cases.

Implementation of Composite Pattern

The Composite pattern consists of two main components: the Component and the Composite.

Component: This is the base interface or abstract class that defines the common methods that both the leaf nodes and composite nodes implement.

Composite: This is the class that contains a collection of leaf nodes and composite nodes. It implements the methods defined in the Component interface and recursively calls those methods on its child components.

Here’s an example implementation of the Composite pattern in Java:

Define the Component interface:

public interface Employee {
public void showDetails();
}


Create leaf nodes that implement the Component interface:

public class Developer implements Employee {
private String name;
private String position;
public Developer(String name, String position) {
    this.name = name;
    this.position = position;
}

public void showDetails() {
    System.out.println("Name: " + name + ", Position: " + position);
}
}

public class Manager implements Employee {
private String name;
private String position;
public Manager(String name, String position) {
    this.name = name;
    this.position = position;
}

public void showDetails() {
    System.out.println("Name: " + name + ", Position: " + position);
}
}


Create a Composite class that implements the Component interface and contains a collection of leaf nodes and composite nodes:

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

public class Department implements Employee {
private List employees = new ArrayList();
public void addEmployee(Employee employee) {
    employees.add(employee);
}

public void removeEmployee(Employee employee) {
    employees.remove(employee);
}

public void showDetails() {
    for (Employee employee : employees) {
        employee.showDetails();
    }
}
}


Use the Composite class to add leaf nodes and composite nodes and call their common methods:

public static void main(String[] args) {
Employee dev1 = new Developer("John", "Senior Developer");
Employee dev2 = new Developer("Mike", "Junior Developer");
Employee manager = new Manager("Mary", "Development Manager");
Department developmentDept = new Department();
developmentDept.addEmployee(dev1);
developmentDept.addEmployee(dev2);
developmentDept.addEmployee(manager);

developmentDept.showDetails();
}


In this example, we define the Component interface Employee that specifies a method for showing employee details. We also define two leaf nodes (Developer and Manager) that implement the Component interface. We then create a Composite class (Department) that contains a collection of Employee objects (leaf nodes and composite nodes). Finally, we use the Composite class to add leaf nodes and composite nodes and call their common methods.

Practical Use Cases of Composite Pattern

  1. Representing hierarchical structures: One of the most common use cases of the Composite pattern is for representing hierarchical structures, such as file systems, organization charts, or menu items. In these scenarios, the Composite pattern lets you treat individual objects and groups of objects in a uniform way, making it easier to navigate and manipulate the structure.
  2. Building complex user interfaces: The Composite pattern is also useful for building complex user interfaces. In this scenario, the Composite pattern allows you to represent complex UI elements as a hierarchy of simpler UI elements. For example, a complex window may contain several sub-windows, each of which contains several buttons, labels, and text fields. By representing this hierarchy using the Composite pattern, you can simplify the code required to create, modify, and display the UI.
  3. Implementing tree data structures: The Composite pattern can also be used to implement tree data structures. In this scenario, the Composite pattern allows you to represent the nodes of the tree as a hierarchy of simpler nodes. For example, a tree data structure representing the files in a file system may have a root node that contains several sub-nodes, each of which represents a directory or file.
  4. Managing complex business processes: The Composite pattern can also be used for managing complex business processes. In this scenario, the Composite pattern allows you to represent the different steps and sub-steps of the business process as a hierarchy of simpler steps. For example, a business process for creating a product may involve several sub-processes, such as designing the product, sourcing raw materials, and manufacturing the product. By representing these sub-processes using the Composite pattern, you can simplify the code required to manage and track the progress of the business process.

Overall, the Composite pattern is a flexible and powerful design pattern that can be used in a variety of practical scenarios. By representing complex structures as hierarchies of simpler structures, the Composite pattern simplifies code, reduces duplication, and makes it easier to work with complex systems.