08 Jan 2025

Composite Pattern

Overview

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

It is commonly used when you have a tree-like structure, such as a file system, where some elements (files) are individual objects and others (directories) are containers of other objects.

Key Participants

  1. Component

  • Defines the interface for all objects in the composition (both leaf and composite).

  • Declares common operations applicable to both simple and complex objects.

  1. Leaf

  • Represents individual objects in the composition that have no children.

  • Implements the Component interface.

  1. Composite

  • Represents complex objects that may have children (other components).

  • Implements methods to manage child components (e.g., add(), remove(), getChild()).

  • Implements the Component interface.

  1. Client

  • Works with objects through the Component interface.

  • Does not need to differentiate between individual (leaf) or composite objects.

Key Methods and Their Purposes

  1. add(Component c): Adds a child component to a composite object.

  1. remove(Component c): Removes a child component from a composite object.

  1. getChild(int index): Returns a specific child component of a composite object.

  1. operation(): Performs an action. This could be implemented differently in Leaf and Composite.

Implementation in Code

Example: File System

// Component
interface FileSystemComponent {
    void showDetails();
}

// Leaf
class File implements FileSystemComponent {
    private String name;

    public File(String name) {
        this.name = name;
    }

    @Override
    public void showDetails() {
        System.out.println("File: " + name);
    }
}

// Composite
class Directory implements FileSystemComponent {
    private String name;
    private List<FileSystemComponent> children = new ArrayList<>();

    public Directory(String name) {
        this.name = name;
    }

    public void add(FileSystemComponent component) {
        children.add(component);
    }

    public void remove(FileSystemComponent component) {
        children.remove(component);
    }

    public FileSystemComponent getChild(int index) {
        return children.get(index);
    }

    @Override
    public void showDetails() {
        System.out.println("Directory: " + name);
        for (FileSystemComponent child : children) {
            child.showDetails();
        }
    }
}

// Client
public class CompositePatternDemo {
    public static void main(String[] args) {
        File file1 = new File("File1.txt");
        File file2 = new File("File2.txt");
        Directory directory = new Directory("MyFolder");

        directory.add(file1);
        directory.add(file2);

        directory.showDetails();
    }
}

Advantages

  1. Uniformity: Treats individual objects and composites the same way.

  1. Extensibility: Easy to add new types of components without affecting the client.

  1. Tree Structure Representation: Natural way to model hierarchical structures.

Disadvantages

  1. Complexity: Managing the composition can become complex, especially when there are many levels.

  1. Overhead: Can introduce additional overhead when managing child components in composites.

Real-World Examples

  1. File System: Files and directories (folders) as individual and composite objects.

  1. Graphic Editor: Shapes (circle, rectangle) as leaf objects, and groups of shapes as composite objects.

  1. Menu System: Individual menu items as leaves, and menus as composites.

When to Use Composite Pattern?

  • When you want to represent part-whole hierarchies.

  • When you want the client to treat individual objects and composites uniformly.

  • When the objects need to be organized into a tree structure.

.

← Back to Library