Composite

Composite

  • Allows us to represent individual entities(leaves) and groups of leaves as the same.
  • Is a structural design pattern that lets you compose objects into a changeable tree structure.
  • Is great if you need the option of swapping hierarchical relationships around.
  • Allows you to add/remove components to the hierarchy.
  • Provides flexibility of structure

Terminology

  • Component Interface: The interface that all leaves and composites should implement.
  • Leaf: A single object that can exist inside or outside a composite.
  • Composite: A collection of leaves and/or other composites.

Composite pattern example

  • Let's say we want to represent the departments hierarchy. The departments are Accounting, Developement and Management. Management is the parent for Accounting and Development.

Let's write the abstract class or an interface for the department.

from abc import ABC, abstractmethod

class BaseDepartment(ABC):
    @abstractmethod
    def __init__(self, num_of_employees):
        pass

    @abstractmethod
    def print_department(self):
        pass

As we have defined the abstract department, let's create the classes for Accounting and Development departments.

class Accounting(BaseDepartment):
    def __init__(self, num_of_employees):
        self.num_of_employees = num_of_employees

    def print_department(self):
        print(f"Accounting employees: {self.num_of_employees}")

class Development(BaseDepartment):
    def __init__(self, num_of_employees):
        self.num_of_employees = num_of_employees

    def print_department(self):
        print(f"Development employees: {self.num_of_employees}")

Now, let's create the parent department Management. It will have child departments.

class Management(BaseDepartment):
    def __init__(self, num_of_employees):
        self.num_of_employees = num_of_employees
        self.childs = []

    def print_department(self):
        print(f"Management base employees: {self.num_of_employees}")
        total_emp_count = self.num_of_employees
        for child in self.childs:
            total_emp_count += child.num_of_employees
            child.print_department()
        print(f'Total employees: {total_emp_count}')

    def add_child_dept(self, dept):
        self.childs.append(dept)

Let's write the client class and use above defined classes.

acc_dept = Accounting(200)
dev_dept = Development(500)

management_dept = Management(50)
management_dept.add(acc_dept)
management_dept.add(dev_dept)

# print dept
management_dept.print_department()

Once we run the above code it will give below output.

Management base employees: 50
Accounting employees: 200
Development employees: 500
Total employees: 750

In the above code Accounting and Development classes are leaf classes and Management is the composite class.

References: