Composite

Buffer this pageShare on FacebookPrint this pageTweet about this on TwitterShare on Google+Share on LinkedInShare on StumbleUpon
Reading Time: 2 minutes

Composite Design Pattern in Python

Composite Design Pattern in Python

Design Patterns Home
 

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
			SoftwareEngineer22

It 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.

Pseduo 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

  1. First, we create the top level entity: topLevelMenu
  2. Then, we create the first level entities: subMenuItem1, subMenuItem2
  3. Then, we create the second level entities: subMenuItem11, subMenuItem12
  4. Then, we append the children to their parents one by one by calling the appendChild() methods.
  5. 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


 

 

 

 


See also:

Buffer this pageShare on FacebookPrint this pageTweet about this on TwitterShare on Google+Share on LinkedInShare on StumbleUpon

Leave a Reply