Reading Time: 2 minutes
Composite Design Pattern in Python
What is it?
The Composite Design Pattern provides an elegant way of making tree data structures, having elements which can have further elements. Consider the following examples:
1. Menu TopLevelMenu SubMenuItem1 SubMenuItem11 SubMenuItem12 SubMenuItem2 2. Hierarchy in an IT Organization ProjectManager TeamLeader1 SoftwareEngineer11 SoftwareEngineer12 TeamLeader2 SoftwareEngineer21 SoftwareEngineer22It is classified under Structural Design Patterns as it provides one of the best methods to organize class hierarchy.
Why the need for it: Problem Statement
There are situations, such as above, when you need to build recursive tree data structures so that elements of the tree can have sub-elements. The Composite Design Pattern helps to realise these hierarchical structures in a hassle-free manner.
Terminology
- Child Element: Class representing elements which are placed at the bottom of the hierarchy tree such as SubMenuItem11, SoftwareEngineer11 etc. in the above examples. These elements do not spawn further elements.
- Composite Element: Class representing elements which are placed at any level of the hierarchy tree except for the bottom level, such as SubMenuItem1, TeamLeader1, ProjectManager etc. in the above examples. These elements spawn further elements. The class maintains the child objects by adding and removing them from the tree structure.
Pseudo Code
class ChildElement: '''Class representing objects at the bottom of the hierarchy tree.''' def __init__(*args): ''''Takes the first positional argument and assigns to member variable "name".''' def printDetails(): '''Prints the name of the child element.''' class CompositeElement: '''Class representing objects at any level of the hierarchy tree except for the bottom level. Maintains the child objects by adding and removing them from the tree structure.''' def __init__(*args): '''Takes the first positional argument and assigns to member variable "name". Initializes a list of children elements.''' def appendChild(child): '''Adds the supplied child element to the list of children elements "children".''' def removeChild(child): '''Removes the supplied child element from the list of children elements "children".''' def printDetails(self): '''Prints the details of the component element first. Then, iterates over each of its children, prints their details by calling their printDetails() method.''' ### CREATING THE TREE DATA STRUCTURE ### create the top level entity, such as 'TopLevelMenu' create the first level entities, such as 'SubMenuItem1', 'SubMenuItem2' create the second level entities, such as 'SubMenuItem11', 'SubMenuItem11' append the children to parents one by one by calling appendChild() methods check to see if the tree was created successfully by calling the printDetails() method of the top level entity.
How to implement it
# We are attempting to make a Menu with sub-items, which may have subsequent sub-items, such as: # TopLevelMenu [Composite] # SubMenuItem1 [Composite] # SubMenuItem11 [Child] # SubMenuItem12 [Child] # SubMenuItem2 [Composite] class ChildElement: '''Class representing objects at the bottom of the hierarchy tree.''' def __init__(self, *args): ''''Takes the first positional argument and assigns to member variable "name".''' self.name = args[0] def printDetails(self): '''Prints the name of the child element.''' print("\t", end = "") print(self.name) class CompositeElement: '''Class representing objects at any level of the hierarchy tree except for the bottom level. Maintains the child objects by adding and removing them from the tree structure.''' def __init__(self, *args): '''Takes the first positional argument and assigns to member variable "name". Initializes a list of children elements.''' self.name = args[0] self.children = [] def appendChild(self, child): '''Adds the supplied child element to the list of children elements "children".''' self.children.append(child) def removeChild(self, child): '''Removes the supplied child element from the list of children elements "children".''' self.children.remove(child) def printDetails(self): '''Prints the details of the component element first. Then, iterates over each of its children, prints their details by calling their printDetails() method.''' print(self.name) for child in self.children: print("\t", end = "") child.printDetails() ### CREATING THE MENU i.e. TREE DATA STRUCTURE ### topLevelMenu = CompositeElement("TopLevelMenu") subMenuItem1 = CompositeElement("SubMenuItem1") subMenuItem2 = CompositeElement("SubMenuItem2") subMenuItem11 = ChildElement("SubMenuItem11") subMenuItem12 = ChildElement("SubMenuItem12") subMenuItem1.appendChild(subMenuItem11) subMenuItem1.appendChild(subMenuItem12) topLevelMenu.appendChild(subMenuItem1) topLevelMenu.appendChild(subMenuItem2) topLevelMenu.printDetails() ##OUTPUT: ##TopLevelMenu ## SubMenuItem1 ## SubMenuItem11 ## SubMenuItem12 ## SubMenuItem2
Walkthrough of implementation
- First, we create the top level entity: topLevelMenu
- Then, we create the first level entities: subMenuItem1, subMenuItem2
- Then, we create the second level entities: subMenuItem11, subMenuItem12
- Then, we append the children to their parents one by one by calling the appendChild() methods.
- Finally, we call the printDetails() method of the top level entity to see if the tree has been created successfully.
Related to: Decorator, Iterator & Visitor
- Creational Patterns
- Factory
- Abstract Factory
- Prototype
- Singleton
- Builder
- Architectural Pattern
- Model View Controller (MVC)