COMPOSITE PATTERN

There are times when you feel a need of a tree data structure in your code. There are many variations to the tree data structure, but sometimes there is a need of a tree in which both branches as well as leafs of the tree should be treated as uniformly.

The Composite Pattern allows you to compose objects into a tree structure to represent the part-whole hierarchy which means you can create a tree of objects that is made of different parts, but that can be treated as a whole one big thing. Composite lets clients to treat individual objects and compositions of objects uniformly, that’s the intent of the Composite Pattern.

In the composite pattern, a tree structure exists where identical operations can be performed on leaves and nodes. A node in a tree is a class that can have children. A node class is a ‘composite’ class. A leaf in a tree is a ‘primitive’ class that does not have children. The children of a composite can be leaves or other composites. The leaf class and the composite class share a common ‘component’ interface that defines the common operations that can be performed on leaves and composites.

When an operation on a composite is performed, this operation is performed on all children of the composite, whether they are leaves or composites. Thus, the composite pattern can be used to perform common operations on the objects that compose a tree.

In Other words, Composite Pattern consists of following objects.

Base Component – Base component is the interface for all objects in the composition, client program uses base component to work with the objects in the composition. It can be an interface or an abstract class with some methods common to all the objects.

Leaf – Defines the behavior for the elements in the composition. It is the building block for the composition and implements base component. It doesn’t have references to other Components.

Composite – It consists of leaf elements and implements the operations in base component.

Example:

Employee.java  (Component)

package com.myjavablog.structural.composite;

/*
First we will create component interface.
It reresents objects in composition.
It has all common operations applicable to both Manager and Developer.
*/

/*
Employee - Component
Developer - Leaf
Manager - Composite
*/

public interface Employee {

public void add(Employee e);
public void remove(Employee e);
public Employee getChild(int i);
public String getName();
public double getSalary();
public void print();
}

Manager.java  (Composite)

/*
Manager is composite class.
Key point here is all common methods delegates its operations to child objects
It has methods to access and modify its children.
*/
package com.myjavablog.structural.composite;

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

public class Manager implements Employee {

private String name;
private double salary;

List<Employee> employeeList = new ArrayList<>();

public Manager(String name, double salary) {
this.name = name;
this.salary = salary;
}

@Override
public void add(Employee e) {
employeeList.add(e);
}

@Override
public void remove(Employee e) {
employeeList.remove(e);
}

@Override
public Employee getChild(int i) {
return employeeList.get(i);
}

@Override
public String getName() {
return this.name;
}

@Override
public double getSalary() {
return this.salary;
}

@Override
public void print() {

System.out.println("=======================================");
System.out.println("Name = "+ this.getName());
System.out.println("Salary = "+ this.getSalary());
System.out.println("=======================================");

Iterator<Employee> employeeIterator = employeeList.iterator();
while(employeeIterator.hasNext()){
Employee emp = employeeIterator.next();
emp.print();
}

}

}

Developer.java (Leaf)

/*
Developer is a leaf node so many methods are not applicable to this class
*/
package com.myjavablog.structural.composite;

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

public class Developer implements Employee {

private String name;
private double salary;

public Developer(String name, double salary) {
this.name = name;
this.salary = salary;
}

@Override
public void add(Employee e) {
//This is a leaf node so this method is not applicable to this class
}

@Override
public void remove(Employee e) {
//This is a leaf node so this method is not applicable to this class
}

@Override
public Employee getChild(int i) {
//This is a leaf node so this method is not applicable to this class
return null;
}

@Override
public String getName() {
return this.name;
}

@Override
public double getSalary() {
return this.salary;
}

@Override
public void print() {

System.out.println("=======================================");
System.out.println("Name = "+ this.getName());
System.out.println("Salary = "+ this.getSalary());
System.out.println("=======================================");

}

}

Runner class  (CompositeTest.java )

package com.myjavablog.structural.composite;

public class CompositeTest {

public static void main(String[] args) {

Employee e1 = new Developer("Jack", 87000);
Employee e2 = new Developer("Steve", 97000);
Employee manager1 = new Manager("Bill", 100000);

manager1.add(e1);
manager1.add(e2);

Employee e3 = new Developer("Daniel", 50000);
Manager gereralManager = new Manager("Mark", 80000);
gereralManager.add(e3);
gereralManager.add(manager1);
gereralManager.print();

}
}

Output:

=======================================
Name = Mark
Salary = 80000.0
=======================================
=======================================
Name = Daniel
Salary = 50000.0
=======================================
=======================================
Name = Bill
Salary = 100000.0
=======================================
=======================================
Name = Jack
Salary = 87000.0
=======================================
=======================================
Name = Steve
Salary = 97000.0
=======================================

Leave a Comment

Bitnami