# Composite Pattern

The Composite Pattern is a structural design pattern that lets you compose objects into tree structures and then work with these structures as if they were individual objects.

## 1. The Core Concept

This pattern is useful when your application's core model can be represented as a tree.
*   **Leaf:** An individual object that does the actual work. It has no children.
*   **Composite:** An object that contains children (Leaves or other Composites). It delegates work to its children.
*   **Component:** A common interface for both Leaves and Composites.

The client treats all objects (Leaves and Composites) uniformly through the Component interface.

## 2. Analogy: A Box of Gifts

Imagine you order a shipment.
*   You receive a big **Box**.
*   Inside, there might be a smaller **Box** and a **Product** (Leaf).
*   Inside the smaller box, there might be more **Products**.

If you want to know the total price, you don't need to unpack everything yourself. You just ask the big Box: "What's your price?".
*   The Box asks its contents.
*   If content is a Product, it returns its price.
*   If content is a Box, it asks *its* contents.
*   The prices bubble up to the top.

## 3. Example (TypeScript)

Let's model a file system.

```typescript
// The Component Interface
interface FileSystemComponent {
    getName(): string;
    getSize(): number;
}

// Leaf
class FileItem implements FileSystemComponent {
    constructor(private name: string, private size: number) {}

    getName(): string { return this.name; }
    getSize(): number { return this.size; }
}

// Composite
class Directory implements FileSystemComponent {
    private children: FileSystemComponent[] = [];

    constructor(private name: string) {}

    add(component: FileSystemComponent) {
        this.children.push(component);
    }

    getName(): string { return this.name; }

    getSize(): number {
        // Delegate to children and sum up
        return this.children.reduce((sum, child) => sum + child.getSize(), 0);
    }
}

// Usage
const root = new Directory("root");
const file1 = new FileItem("file1.txt", 10);
const subDir = new Directory("subdir");
const file2 = new FileItem("file2.txt", 20);

subDir.add(file2);
root.add(file1);
root.add(subDir);

console.log(root.getSize()); // Output: 30 (10 + 20)
```

## 4. Pros and Cons

| Pros | Cons |
| :--- | :--- |
| **Uniformity:** You can treat simple and complex elements the same way. | **Generalization:** It might be difficult to provide a common interface for classes whose functionality differs too much. |
| **Open/Closed:** You can introduce new element types without breaking existing code. | **Type Safety:** You can't restrict the types of components a composite can hold (unless you check at runtime). |
| **Recursion:** Makes it easy to work with recursive structures. | |

## 5. Recursive Composition

The power of the Composite pattern lies in its ability to create complex tree structures that can be treated as a single object. This is achieved through **Recursive Composition**.

*   **Infinite Depth:** A Composite can contain other Composites, which can contain other Composites, and so on.
*   **Simple Client Code:** The client code doesn't need to know if it's dealing with a simple Leaf or a complex tree of Composites. It just calls `operation()`.
*   **Execution:** When `operation()` is called on a Composite, it iterates through its children and calls `operation()` on them. If a child is also a Composite, it repeats the process. This recursion continues until it hits the Leaves, which perform the actual work.

[[programming/design-patterns]]
[[programming/object-oriented-programming]]
[[programming/iterator-pattern]]