Composite Design Pattern: Structural patterns

Share the Article

What

Composite design pattern is a type of structural pattern which deals with composition of objects. It treats individual objects and a composition of objects in the same manner.

Composite pattern is mainly used if we have tree like structure of our application data. This means, the application has objects in the form of root and leaves concept. The root is the composition of leaf objects as well as sub-trees. In other words, the composite pattern best suits for whole-part hierarchy where, whole consists of several part objects.

Why

Lets us try to understand the need of composite design pattern by taking an example of an application performing the below job :

  • Firstly, get a list all the schools in the city.
  • Secondly, list all the classes in those school.
  • Finally, display all student names in every class.

Basically, for designing such an application we need to create below objects:

  • School List is one object (root level) which consists of several school objects
  • School (sub-hierarchy) is again one more object and it consists of several class objects.
  • Class is again one object sub-hierarchy which consists of several students.
  • Finally, a Student object is an independent entity.

Lets try to depict the tree diagram for above application:

composite design pattern example

Obviously, for the above application, there exists a whole-part hierarchy.

Solution without using Composite Design Pattern

One method of designing such application is without design patterns. In this case, we need to create your own class hierarchy and interfaces for managing addition of schools, classes and students. However, if there are separate interfaces for schools, classes and students, then the application shall become very complex and difficult to understand. Also, the addition of a new component also shall become difficult.

Therefore, for solving above such problem, composite pattern is the best fit.

How

Lets us try to design above application with Composite design pattern.

We need to follow below rules for implementing Composite design pattern:

Identify the leaf and root components

In the application, ensure that leaf components are embedded inside root components. For above application, we are having below leaf and root components.

  1. Student as leaf for Class.
  2. Class as leaf for School.
  3. School as leaf for School List.

Therefore, following is the class design for above application:

class Student //Leaf-level { }; class Class //sub-hierarchy { list<student *> m_studentList; }; class School //sub-hierarchy { list<Class*>m_classList; }; class SchoolList //root-level { list<School*>m_schoolList; };

Create common interface in all the classes

This is needed, so that user can invoke, both root as well leaf member functions through common interface. In this example, the job of the above application is to show details of every school, class and student. Hence, we add a common interface “showDetail( )” in all the classes.

class Student { public: void showDetail(); }; class Class { list<student *> m_studentList; public: void showDetail(); }; class School { list<Class*>m_classList; public: void showDetail(); }; class SchoolList { list<School*>m_schoolList; public: void showDetail(); };

Solution with Composite Design Pattern

Below is the complete code for the application which is printing all the details:

#include<iostream> //main header #include<string> //for string #include<list> //for stl list< > using namespace std;//for namespace class Student { string m_name; public: Student(string name) :m_name(name) { } void showDetail() { cout << m_name << endl; } }; class StudentList { list<Student*> s1; public: void AddStudent(Student *student) { s1.push_back(student); } void showDetail() { auto it1 = s1.begin(); auto it2 = s1.end(); cout<<" Student Details"<<endl; while (it1 != it2) { (*it1)->showDetail(); it1++; } } }; class ClassList { StudentList *listOfStudent; string m_name; public: ClassList(string name) :m_name(name) { listOfStudent=new StudentList; } void AddStudent(Student *student) { listOfStudent->AddStudent(student); } void showDetail() { cout << "Class Standard " << m_name << endl; listOfStudent->showDetail(); } ~ClassList() { delete listOfStudent; } }; class SchoolList { list<ClassList*> cl1; string m_name; public: SchoolList(string name) :m_name(name) { } void AddSchool(ClassList *schoolClassList) { cl1.push_back(schoolClassList); } void showDetail() { cout << " School Name is " << m_name << endl; auto it1 = cl1.begin(); auto it2 = cl1.end(); while (it1 != it2) { (*it1)->showDetail(); it1++; } } }; int main() //client-code { SchoolList *sl1 =new SchoolList("Green Valley"); ClassList *cl1 = new ClassList("1"); Student *s1 = new Student("jacob"); Student *s2 = new Student("Ajay"); Student *s3 = new Student("Vinay"); cl1->AddStudent(s1); cl1->AddStudent(s2); cl1->AddStudent(s3); sl1->AddSchool(cl1); sl1->showDetail(); return 0; }

As seen above with Composite design pattern, we have developed the School list application very easily. If in future, there is need to add one more list, for instance, a city list for schools, then such requestcan also be very easily added.

Pros & Cons of Composite Design Pattern

Pros

  • This pattern solves a problem related to tree structure application in very easy manner
  • It supports future enhancement for tree with less impact.

Cons

  • Composite pattern is complex to design due to his hierarchy.

Main Funda: Composite Design Pattern provides easy traversal of tree like structures.

Advanced C++ Topics

Abstract Factory Design Pattern
Singleton Design Pattern
Factory Method Design Pattern
Builder Design Pattern
Adapter Design Pattern
Prototype Design Pattern
Facade Design Pattern
Bridge Design Pattern
What is reference collapsing?

Share the Article

Leave a Reply

Your email address will not be published. Required fields are marked *