# Abstract Factory Pattern

The Abstract Factory Pattern is a creational design pattern that lets you produce families of related or dependent objects without specifying their concrete classes.

## 1. The Core Concept

While the **Factory Method** creates one product, the **Abstract Factory** creates a *family* of products. Clients work with factories and products through abstract interfaces, so they don't need to know which concrete classes they are using.

*   **Abstract Factory:** Declares an interface for creating each distinct product in a product family.
*   **Concrete Factory:** Implements the creation methods for a specific variant of the product family.
*   **Abstract Product:** Declares an interface for a type of product.
*   **Concrete Product:** Implements the product interface for a specific variant.

## 2. Analogy: Furniture Shop

Imagine a furniture shop simulator. You have a family of products: **Chair**, **Sofa**, **CoffeeTable**.
You also have variants (styles): **Modern**, **Victorian**, **ArtDeco**.

*   If a customer wants a **Modern** living room, they need a `ModernChair`, `ModernSofa`, and `ModernCoffeeTable`.
*   You don't want to accidentally give them a `VictorianChair` with a `ModernSofa`.
*   The `ModernFurnitureFactory` ensures all products created match the "Modern" style.

## 3. Example (TypeScript)

Let's build a cross-platform GUI toolkit (Windows vs. Mac).

```typescript
// Abstract Products
interface Button {
    paint(): void;
}

interface Checkbox {
    paint(): void;
}

// Concrete Products (Windows)
class WinButton implements Button {
    paint() { console.log("Rendering Windows Button"); }
}
class WinCheckbox implements Checkbox {
    paint() { console.log("Rendering Windows Checkbox"); }
}

// Concrete Products (Mac)
class MacButton implements Button {
    paint() { console.log("Rendering Mac Button"); }
}
class MacCheckbox implements Checkbox {
    paint() { console.log("Rendering Mac Checkbox"); }
}

// Abstract Factory
interface GUIFactory {
    createButton(): Button;
    createCheckbox(): Checkbox;
}

// Concrete Factories
class WinFactory implements GUIFactory {
    createButton(): Button { return new WinButton(); }
    createCheckbox(): Checkbox { return new WinCheckbox(); }
}

class MacFactory implements GUIFactory {
    createButton(): Button { return new MacButton(); }
    createCheckbox(): Checkbox { return new MacCheckbox(); }
}

// Client Code
function createUI(factory: GUIFactory) {
    const button = factory.createButton();
    const checkbox = factory.createCheckbox();
    
    button.paint();
    checkbox.paint();
}

// Usage
createUI(new WinFactory()); // Output: Rendering Windows Button, Rendering Windows Checkbox
createUI(new MacFactory()); // Output: Rendering Mac Button, Rendering Mac Checkbox
```

## 4. Pros and Cons

| Pros | Cons |
| :--- | :--- |
| **Consistency:** Ensures that products you use together match each other (same variant). | **Complexity:** Introduces a lot of new interfaces and classes. |
| **Decoupling:** Client code is not coupled to concrete product classes. | **Rigidity:** Adding a new product type (e.g., "Table") to the family requires changing the Abstract Factory interface and *all* concrete factories. |
| **SRP:** Creation code is centralized in one place. | |

[[programming/design-patterns]]
[[programming/object-oriented-programming]]
[[programming/factory-method-pattern]]