GoF Definition: Compose objects into tree structures to represent part-whole hierarchies. The composite pattern lets clients treat individual objects and compositions of objects uniformly.
This pattern can show part-whole hierarchy among objects. A client can treat a composite object just like a single object. In object-oriented programming, we make a composite object when we have many objects with common functionalities. This relationship is also termed a “has-a” relationship among objects.
We can think of any organization that has many departments, and in turn each department has many employees to serve. Please note that actually all are employees of the organization. Groupings of employees create a department, and those departments ultimately can be grouped together to build the whole organization.
Any tree structure in computer science can follow a similar concept.
In this example we are showing a college organization. We have a Principal and two Heads of Departments: one for computer science and one for mathematics. At present, in the mathematics department, we have two lecturers; in the computer science department we have three lecturers. At the end, one lecturer from the computer science department retires/leaves. We have represented the scenario with the following simple example.
High-level structure of the parts of the program is as follows:
package composite.pattern.demo;
import java.util.*;
interface ITeacher
{
public String getDetails();
}
class Teacher implements ITeacher
{
private String teacherName;
private String deptName;
private List<ITeacher> controls;
Teacher(String teacherName, String deptName)
{
this.teacherName = teacherName;
this.deptName = deptName;
controls = new ArrayList<ITeacher>();
}
public void Add(Teacher teacher)
{
controls.add(teacher);
}
public void Remove(Teacher teacher)
{
controls.remove(teacher);
}
public List<ITeacher> getControllingDepts()
{
return controls;
}
@Override
public String getDetails() {
return (teacherName + " is the " + deptName);
}
}
class CompositePatternEx
{
public static void main(String[] args)
{
Teacher Principal = new Teacher("Dr.S.Som","Principal");
Teacher hodMaths = new Teacher("Mrs.S.Das","Hod-Math");
Teacher hodCompSc = new Teacher("Mr. V.Sarcar","Hod-ComputerSc.");
Teacher mathTeacher1 = new Teacher("Math Teacher-1","MathsTeacher");
Teacher mathTeacher2 = new Teacher("Math Teacher-2","MathsTeacher");
Teacher cseTeacher1 = new Teacher("CSE Teacher-1","CSETeacher");
Teacher cseTeacher2 = new Teacher("CSE Teacher-2","CSETeacher");
Teacher cseTeacher3 = new Teacher("CSE Teacher-3","CSETeacher");
//Principal is on top of college
/*HOD -Maths and Comp. Sc. directly reports to him*/
Principal.Add(hodMaths);
Principal.Add(hodCompSc);
/*Teachers of Mathematics directly reports to HOD-Maths*/
hodMaths.Add(mathTeacher1);
hodMaths.Add(mathTeacher2);
/*Teachers of Computer Sc. directly reports to HOD-Comp.Sc.*/
hodCompSc.Add(cseTeacher1);
hodCompSc.Add(cseTeacher2);
hodCompSc.Add(cseTeacher3);
/*Leaf nodes. There is no department under Mathematics*/
mathTeacher1.Add(null);
mathTeacher2.Add(null);
/*Leaf nodes. There is no department under CSE.*/
cseTeacher1.Add(null);
cseTeacher2.Add(null);
cseTeacher3.Add(null);
//Printing the details
System.out.println("***COMPOSITE PATTERN DEMO ***");
System.out.println(" The college has following structure ");
System.out.println(Principal.getDetails());
List<ITeacher> hods=Principal.getControllingDepts();
for(int i=0;i<hods.size();i++)
{
System.out.println(" "+hods.get(i).getDetails());
}
List<ITeacher> mathTeachers=hodMaths.getControllingDepts();
for(int i=0;i<mathTeachers.size();i++)
{
System.out.println(" "+mathTeachers.get(i).getDetails());
}
List<ITeacher> cseTeachers=hodCompSc.getControllingDepts();
for(int i=0;i<cseTeachers.size();i++)
{
System.out.println(" "+cseTeachers.get(i).getDetails());
}
//One computer teacher is leaving
hodCompSc.Remove(cseTeacher2);
System.out.println(" After CSE Teacher-2 leaving the organization- CSE department has following employees:");
cseTeachers = hodCompSc.getControllingDepts();
for(int i=0;i<cseTeachers.size();i++)
{
System.out.println(" "+cseTeachers.get(i).getDetails());
}
}
}
What is the best data structure to store components?
There is no universal rule. It depends on the requirement (e.g., efficiency). We can use linked list, trees, arrays, etc., based on our demand. GoF also suggests that it is not mandatory to use any general-purpose data structure.