Python Composite Design Pattern

1. Definition

The Composite Design Pattern allows you to compose objects into tree structures to represent part-whole hierarchies. It treats both individual objects and composites (groups of objects) uniformly.

2. Problem Statement

Imagine you have to implement a system to represent and manage a graphic drawing made up of lines, rectangles, circles, and even groups of these shapes. If every shape is treated differently, it becomes challenging to manage the entire drawing or perform operations on it uniformly.

3. Solution

The Composite pattern suggests treating both simple (leaf) and complex (composite) objects uniformly. In this case, both leaf and composite objects implement the same interface. The composite object contains a group of children and forwards requests to them.

4. Real-World Use Cases

1. Graphics drawing applications where shapes can be grouped.

2. Organization hierarchies where an individual could be an employee or a manager with subordinates.

3. File system representations with files and directories.

5. Implementation Steps

1. Define a component interface with methods suitable for both leaf and composite objects.

2. Create leaf objects that implement the component interface.

3. Create composite objects that also implement the component interface and have a collection of children.

4. Composite objects forward requests to their children and might also implement additional behaviors.

6. Implementation in Python

# Component Interface
class Graphic:
    def draw(self):
        pass
# Leaf
class Line(Graphic):
    def draw(self):
        return "Drawing a Line"
class Circle(Graphic):
    def draw(self):
        return "Drawing a Circle"
# Composite
class GraphicGroup(Graphic):
    def __init__(self):
        self._graphics = []
    def add(self, graphic):
        self._graphics.append(graphic)
    def draw(self):
        results = ["Drawing a Group:"]
        for graphic in self._graphics:
            results.append(graphic.draw())
        return "\n".join(results)
# Client Code
line = Line()
circle = Circle()
group = GraphicGroup()
group.add(line)
group.add(circle)
print(group.draw())

Output:

Drawing a Group:
Drawing a Line
Drawing a Circle

Explanation:

1. Graphic is the component interface that declares drawing operations.

2. Line and Circle are leaf objects implementing the Graphic interface.

3. GraphicGroup is a composite object that contains a list of Graphic components (both leafs and other composites) and forwards the draw request to them.

4. In the client code, a line, circle, and group (composite) are created. Both the line and circle are added to the group, and the entire group is drawn.

7. When to use?

The Composite Pattern is useful when:

1. You want to represent hierarchies of objects.

2. You need to treat individual objects and composites of objects uniformly.

3. The structure can have any level of complexity, and you want to simplify client code by treating all objects the same.


Comments