Sobes.tech
Middle
219

What is the Composite pattern?

Answer from AI

sobes.tech AI

The Composite Pattern is a structural design pattern that allows objects to be composed into tree structures to represent hierarchies of "part-whole". The pattern enables clients to treat individual objects and compositions of objects uniformly.

Principles of the pattern:

  1. Uniform interface: Both individual objects ("Leaves") and their containers ("Branches") implement a common interface.
  2. Recursive structure: Branches can contain both Leaves and other Branches.
  3. Transparency for the client: Client code interacts with objects through a common interface and does not distinguish between Leaf and Branch (in the simplest case).

Main elements:

  • Component: Declares the common interface for all objects in the structure.
  • Leaf: Represents individual objects that do not contain other components.
  • Composite: Represents objects that can contain other components (both Leaves and other Composites). Implements operations to manage child components.

Example structure:

// Base component (abstract class or interface)
class Component:
    def operation(self):
        pass

// Leaf (individual object)
class Leaf(Component):
    def __init__(self, name):
        self.name = name

    def operation(self):
        print(f"Performing operation on Leaf '{self.name}'")

// Branch (composite object)
class Composite(Component):
    def __init__(self, name):
        self.name = name
        self._children = []

    def add(self, component):
        self._children.append(component)

    def remove(self, component):
        self._children.remove(component)

    def operation(self):
        print(f"Performing operation on Composite '{self.name}'")
        for child in self._children:
            child.operation()

// Usage
root = Composite("Root")

branch1 = Composite("Branch 1")
leaf1 = Leaf("Leaf 1A")
leaf2 = Leaf("Leaf 1B")

branch1.add(leaf1)
branch1.add(leaf2)

branch2 = Composite("Branch 2")
leaf3 = Leaf("Leaf 2A")
branch2.add(leaf3)

root.add(branch1)
root.add(branch2)

leaf4 = Leaf("Leaf 4")
root.add(leaf4)

root.operation() // Calls operation() recursively throughout the tree

Advantages:

  • Easy to add new types of components (Leaves or Branches).
  • Simplifies client code through a unified interface.
  • Flexibility in representing hierarchical structures.

Disadvantages:

  • Can complicate the interface of the base component if management operations for children (such as add and remove) are included in it. Leaves that cannot have children are forced to implement these methods, which violates the Single Responsibility Principle (can be addressed with interfaces).
  • Sometimes it is difficult to restrict which types of components can be added to a specific Branch.

Applicability:

  • When there is a need to represent hierarchical structures of "part-whole" objects.
  • When clients should be able to treat individual objects and groups of objects uniformly.
  • Examples: file system (files - leaves, folders - branches), GUI elements (individual fields - leaves, panels and windows - branches), company structures (employees - leaves, departments - branches).