https://dzone.com/articles/composite-design-pattern-in-java-1
The composite pattern is meant to "compose objects into a tree structure to represent part-whole hierarchies. Composite lets clients treat individual objects and compositions of objects uniformly"
- Composite design patterns describe groups of objects that can be treated in the same way as a single instance of the same object type.
- The composite pattern allows us to "compose" objects into tree structures to represent part-whole hierarchies.
- In addition, the composite patterns also allow our clients to treat individual objects and compositions in the same way.
- Composite patterns allow us to have a tree structure for each node that performs a task.
- In object-oriented programming, a composite is an object designed as a composition of one-or-more similar objects, all exhibiting similar functionality. This is known as a “has-a”relationship between objects.
Below is the list of classes/objects used in the composite pattern, which has four :
- Component – Component is the interface (or abstract class) for the composition of the objects and methods for accessing/processing its child or node components. It also implements a default interface to define common functionalities/behaviors for all component classes.
- Leaf – The leaf class defines a concrete component class, which does not have any further composition. The leaf class implements the component interface. It performs the command/task at its end only.
- Composite – The composite class defines a concrete component class, which stores its child components. The composite class implements the component interface. It forwards the command/task to the composite objects it contains. It may also perform additional operations before and after forwarding the command/task.
- Client – The client class uses the component interface to interact/manipulate the objects in the composition (Leaf and Composite).
To better understand this, let's take a look at an example of employees working in an organization.
Steps
- We create an interface to define functionalities we like to perform as composite and leaf objects. Below is the code of the
Work
interface, which has methods forassignWork()
andperformWork()
. TheWork
interface will act as a component of the composite pattern in the example.
package design.composite;public interface Work { void assignWork(Employee manager, String work); void performWork();}
- We will create an abstract class of
Employee
to carry the common code for all various concrete subclasses of the employees.
package design.composite;public abstract class Employee implements Work { protected long employeeId; protected String employeeName; protected String designation; protected Department department; public Employee(long employeeId, String employeeName, String designation, Department department) { super(); this.employeeId = employeeId; this.employeeName = employeeName; this.designation = designation; this.department = department; } public long getEmployeeId() { return employeeId; } public void setEmployeeId(long employeeId) { this.employeeId = employeeId; } public String getEmployeeName() { return employeeName; } public void setEmployeeName(String employeeName) { this.employeeName = employeeName; } public String getDesignation() { return designation; } public void setDesignation(String designation) { this.designation = designation; } public Department getDepartment() { return department; } public void setDepartment(Department department) { this.department = department; } @Override public String toString() { StringBuilder builder = new StringBuilder(); builder.append("Employee [").append(employeeId) .append(", ").append(employeeName) .append(", ").append(Designation) .append(", ").append(department) .append("]"); return builder.toString(); }}
- Now, we will create two concrete subclasses of the
Employee
—Manager
andEngineer
. For this, I am keeping the example simple to keep a focus on the pattern. - We will create the
Engineer
class to use as theLeaf
object and, hence, does not have any other employee object as a reference via composition.
package design.composite;public class Engineer extends Employee { private String work; public Engineer(long employeeId, String employeeName, String designation, Department department) { super(employeeId, employeeName, designation, department); } @Override public void assignWork(Employee manager, String work) { this.work = work; System.out.println(this + " has assigned work of '" + work + "' by manager " + manager); } @Override public void performWork() { System.out.println(this + " is performing work of '" + work + "'"); }}
- We will create the
Manager
class to use as the composite object, and we will have another Employee object as a collection via the composition.
package design.composite;import java.util.ArrayList;import java.util.List;public class Manager extends Employee { protected ListmanagingEmployees = new ArrayList (); public Manager(long employeeId, String employeeName, String designation, Department department) { super(employeeId, employeeName, designation, department); } public boolean manages(Employee employee) { return managingEmployees.add(employee); } public boolean stopManaging(Employee employee) { return managingEmployees.remove(employee); } @Override public void assignWork(Employee manager, String work) { System.out.println(this + " has assigned work of '" + work + "' by manager " + manager); System.out.println(); System.out.println(this + " distributing work '" + work + "' to managing-employees.."); managingEmployees.stream().forEach(employee -> { System.out.println("Assigning to " + employee); employee.assignWork(this, work); }); System.out.println(); System.out.println(this + " distributed work of '" + work + "'"); System.out.println(); } @Override public void performWork() { System.out.println(this + " is asking his managing employees to perfom assigned work"); System.out.println(); managingEmployees.stream().forEach(employee -> employee.performWork()); System.out.println(); System.out.println(this + " has completed assigned work with the help of his manahging employees"); System.out.println(); }}
- In the end, we will write the
Main
class as theClien
to execute and test our composite pattern code.
package design.composite;public class Main {public static void main(String[] args) { Engineer ajay = new Engineer(1001l, "Ajay", "Developer", Department.ENG); Engineer vijay = new Engineer(1002l, "Vijay", "SR. Developer", Department.ENG); Engineer jay = new Engineer(1003l, "Jay", "Lead", Department.ENG); Engineer martin = new Engineer(1004l, "Martin", "QA", Department.ENG); Manager kim = new Manager(1005l, "Kim", "Manager", Department.ENG); Engineer anders = new Engineer(1006l, "Andersen", "Developer", Department.ENG); Manager niels = new Manager(1007l, "Niels", "Sr. Manager", Department.ENG); Engineer robert = new Engineer(1008l, "Robert", "Developer", Department.ENG); Manager rachelle = new Manager(1009l, "Rachelle", "Product Manager", Department.ENG); Engineer shailesh = new Engineer(1010l, "Shailesh", "Engineer", Department.ENG); kim.manages(ajay); kim.manages(martin); kim.manages(vijay); niels.manages(jay); niels.manages(anders); niels.manages(shailesh); rachelle.manages(kim); rachelle.manages(robert); rachelle.manages(niels); rachelle.assignWork(rachelle, "develop web-service code for Product Catalogue"); rachelle.performWork();}}
- Below is the output of the program:
Employee [1009, Rachelle, Product Manager, ENG] has assigned work of 'develop web-service code for Product Catalogue' by manager Employee [1009, Rachelle, Product Manager, ENG]Employee [1009, Rachelle, Product Manager, ENG] distributing work 'develop web-service code for Product Catalogue' to managing-employees..Assigning to Employee [1005, Kim, Manager, ENG]Employee [1005, Kim, Manager, ENG] has assigned work of 'develop web-service code for Product Catalogue' by manager Employee [1009, Rachelle, Product Manager, ENG]Employee [1005, Kim, Manager, ENG] distributing work 'develop web-service code for Product Catalogue' to managing-employees..Assigning to Employee [1001, Ajay, Developer, ENG]Employee [1001, Ajay, Developer, ENG] has assigned work of 'develop web-service code for Product Catalogue' by manager Employee [1005, Kim, Manager, ENG]Assigning to Employee [1004, Martin, QA, ENG]Employee [1004, Martin, QA, ENG] has assigned work of 'develop web-service code for Product Catalogue' by manager Employee [1005, Kim, Manager, ENG]Assigning to Employee [1002, Vijay, SR. Developer, ENG]Employee [1002, Vijay, SR. Developer, ENG] has assigned work of 'develop web-service code for Product Catalogue' by manager Employee [1005, Kim, Manager, ENG]Employee [1005, Kim, Manager, ENG] distributed work of 'develop web-service code for Product Catalogue'Assigning to Employee [1008, Robert, Developer, ENG]Employee [1008, Robert, Developer, ENG] has assigned work of 'develop web-service code for Product Catalogue' by manager Employee [1009, Rachelle, Product Manager, ENG]Assigning to Employee [1007, Niels, Sr. Manager, ENG]Employee [1007, Niels, Sr. Manager, ENG] has assigned work of 'develop web-service code for Product Catalogue' by manager Employee [1009, Rachelle, Product Manager, ENG]Employee [1007, Niels, Sr. Manager, ENG] distributing work 'develop web-service code for Product Catalogue' to managing-employees..Assigning to Employee [1003, Jay, Lead, ENG]Employee [1003, Jay, Lead, ENG] has assigned work of 'develop web-service code for Product Catalogue' by manager Employee [1007, Niels, Sr. Manager, ENG]Assigning to Employee [1006, Andersen, Developer, ENG]Employee [1006, Andersen, Developer, ENG] has assigned work of 'develop web-service code for Product Catalogue' by manager Employee [1007, Niels, Sr. Manager, ENG]Assigning to Employee [1010, Shailesh, Engineer, ENG]Employee [1010, Shailesh, Engineer, ENG] has assigned work of 'develop web-service code for Product Catalogue' by manager Employee [1007, Niels, Sr. Manager, ENG]Employee [1007, Niels, Sr. Manager, ENG] distributed work of 'develop web-service code for Product Catalogue'Employee [1009, Rachelle, Product Manager, ENG] distributed work of 'develop web-service code for Product Catalogue'Employee [1009, Rachelle, Product Manager, ENG] is asking his managing employees to perfom assigned workEmployee [1005, Kim, Manager, ENG] is asking his managing employees to perfom assigned workEmployee [1001, Ajay, Developer, ENG] is performing work of 'develop web-service code for Product Catalogue'Employee [1004, Martin, QA, ENG] is performing work of 'develop web-service code for Product Catalogue'Employee [1002, Vijay, SR. Developer, ENG] is performing work of 'develop web-service code for Product Catalogue'Employee [1005, Kim, Manager, ENG] has completed assigned work with the help of his manahging employeesEmployee [1008, Robert, Developer, ENG] is performing work of 'develop web-service code for Product Catalogue'Employee [1007, Niels, Sr. Manager, ENG] is asking his managing employees to perfom assigned workEmployee [1003, Jay, Lead, ENG] is performing work of 'develop web-service code for Product Catalogue'Employee [1006, Andersen, Developer, ENG] is performing work of 'develop web-service code for Product Catalogue'Employee [1010, Shailesh, Engineer, ENG] is performing work of 'develop web-service code for Product Catalogue'Employee [1007, Niels, Sr. Manager, ENG] has completed assigned work with the help of his manahging employeesEmployee [1009, Rachelle, Product Manager, ENG] has completed assigned work with the help of his manahging employees