# Decorator Pattern

The Decorator Pattern is a structural design pattern that allows you to attach new behaviors to objects by placing these objects inside special wrapper objects that contain the behaviors.

## 1. The Core Concept

Inheritance is static. You can't add a new method to an object at runtime using inheritance. The Decorator pattern uses **Composition** to wrap an object with another object that adds functionality.

*   **Wrapper:** The decorator has the same interface as the target object. It delegates requests to the target but can perform actions before or after the delegation.
*   **Stacking:** You can wrap an object in multiple decorators (e.g., `EncryptionDecorator(CompressionDecorator(DataSource))`).

## 2. Analogy: Clothing

You are a human object.
*   If you are cold, you wrap yourself in a `Sweater`.
*   If it's raining, you wrap yourself in a `Raincoat` (on top of the sweater).
*   You are still "You", but your behavior (warmth, dryness) has been extended.

## 3. Example (TypeScript)

Imagine a notification system.

```typescript
// The Component Interface
interface Notifier {
    send(message: string): void;
}

// Concrete Component
class EmailNotifier implements Notifier {
    send(message: string): void {
        console.log(`Sending Email: ${message}`);
    }
}

// Base Decorator
class BaseDecorator implements Notifier {
    protected wrappee: Notifier;

    constructor(notifier: Notifier) {
        this.wrappee = notifier;
    }

    send(message: string): void {
        this.wrappee.send(message);
    }
}

// Concrete Decorator 1
class SMSDecorator extends BaseDecorator {
    send(message: string): void {
        super.send(message);
        console.log(`Sending SMS: ${message}`);
    }
}

// Concrete Decorator 2
class SlackDecorator extends BaseDecorator {
    send(message: string): void {
        super.send(message);
        console.log(`Sending Slack: ${message}`);
    }
}

// Usage
let stack = new EmailNotifier();
stack = new SMSDecorator(stack);
stack = new SlackDecorator(stack);

stack.send("Hello World!");
// Output:
// Sending Email: Hello World!
// Sending SMS: Hello World!
// Sending Slack: Hello World!
```

## 4. Pros and Cons

| Pros | Cons |
| :--- | :--- |
| **Flexibility:** More flexible than inheritance. Add/remove responsibilities at runtime. | **Complexity:** Can result in many small classes. |
| **SRP:** You can split a monolithic class into several smaller classes. | **Identity:** A decorator and its component are not the same object type (if checking `instanceof`). |
| **Combination:** Combine behaviors by wrapping objects in multiple decorators. | **Configuration:** Initializing a stack of wrappers can be ugly code. |

[[programming/design-patterns]]
[[programming/composition-over-inheritance]]
[[programming/proxy-pattern]]