opencodez

Java Structural Design Patterns – Composite Pattern

Composite Pattern is considered as a Structural Design Pattern. This pattern describes a group of objects and treating them as an individual instance of the same type of object because all exhibiting similar functionality.

In this pattern, we compose objects and creates a tree structure and represents part-whole hierarchies. Each node in the tree performs some task. In object-oriented programming, this is known as a “has-a” relationship between objects.

If you find that in your application code you are using multiple objects in the same way, and often have nearly identical code to handle each of them, then Composite Pattern is a good choice

The pattern defines below concepts-

Composite Pattern by Example

For understanding, we will take a simple example of company hierarchy. In this, we will have a General Manager, Manager, and Developer. If we refer above diagram, in our example we will try to create something like below 

Let us define the component-

public interface Employee {
	public void print();
}

The component interface is very simple and defines a print method.

We will define 2 composites as

public class Manager implements Employee {
	
	private String name;
	ListxEmployeex reportees = new ArrayListxx();
	
	public Manager(String name) {
		this.name = name;
	}
	
	public void addReportee(Employee e) {
		reportees.add(e);
	}
	
	public void remove(Employee e) {
		reportees.remove(e);
	}

	@Override
	public void print() {
		System.out.println(name);
		System.out.println("Reportees..");	
		for(Employee e : reportees) {
			e.print();
		}
	}

}

and

public class GeneralManager implements Employee {
	
	private String name;
	ListxEmployeex reportees = new ArrayListxx();
	
	public GeneralManager(String name) {
		this.name = name;
	}
	
	public void addReportee(Employee e) {
		reportees.add(e);
	}
	
	public void remove(Employee e) {
		reportees.remove(e);
	}

	@Override
	public void print() {
		System.out.println(name);		
		System.out.println("Reportees..");	
		for(Employee e : reportees) {
			e.print();
		}
	}

}

Both the above composites are similar and they have a way to store their leaf nodes or you can say direct reportees.

Now let us add leaf component-

public class Developer implements Employee {
	
	private String name;
	
	public Developer(String name) {
		this.name = name;
	}
	
	@Override
	public void print() {
		System.out.println(name);
	}

}

Running the example

public class CompositeDemo {

	public static void main(String[] args) {
		Developer dev1 = new Developer("Developer 1");
		Developer dev2 = new Developer("Developer 2");
		Developer dev3 = new Developer("Developer 3");
		Developer dev4 = new Developer("Developer 4");
		
		Manager mgr1 = new Manager("Manager 1");
		Manager mgr2 = new Manager("Manager 2");
		
		GeneralManager gmgr = new GeneralManager("General Manager");
		
		gmgr.addReportee(mgr1);
		gmgr.addReportee(mgr2);
		
		gmgr.addReportee(dev3);
		
		mgr1.addReportee(dev1);
		mgr1.addReportee(dev4);
		
		mgr2.addReportee(dev2);
		
		gmgr.print();
		
	}

}

The main program acts as a client and creates a hierarchy. If we run the example we will get below output.

General Manager
Reportees..
Manager 1
Reportees..
Developer 1
Developer 4
Manager 2
Reportees..
Developer 2
Developer 3

The program prints Composite and their Children.

Conclusion

As mentioned earlier when clients need to ignore the difference between compositions of objects and individual objects you can use this pattern. Also, if programmers find that they are using multiple objects in the same way, and often have nearly identical code to handle each of them, then the composite pattern is a good choice. The source code is available in our Github repository.

Download Code