Logo

dev-resources.site

for different kinds of informations.

Learn Design Patterns: Understanding the Abstract Factory Pattern

Published at
12/20/2024
Categories
designpatterns
typescript
softwaredevelopment
Author
Sami Maachi
Learn Design Patterns: Understanding the Abstract Factory Pattern

Design patterns are essential for building scalable and maintainable software. One creational design pattern, the Abstract Factory Pattern ,stands out as a way to manage families of related objects without being tightly coupled to their concrete implementations.

This article will explore the Abstract Factory Pattern, understand its significance through a real-world scenario, and demonstrate its implementation using TypeScript.

Table of Contents

  1. Abstract Factory Definition

  2. Scenario: Understanding the Problem

  3. Real-Life Projects That Use the Abstract Factory

1.Abstract Factory Definition

The Abstract Factory Pattern is a creational design pattern that provides an interface for creating families of related or dependent objects without specifying their concrete classes.

Instead of relying on direct instantiation, this pattern abstracts the object creation process, ensuring that all objects created belong to a specific family.

2.Scenario: Understanding the Problem

Imagine we are building a cross-platform UI toolkit. the toolkit must support multiple platforms — Windows, macOS, and Linux.

Each platform has its own UI components, such as buttons, checkboxes, and dropdown menus. For example:

  • Windows has a WindowsButton, WindowsCheckbox, and WindowsDropdown.

  • macOS has a MacButton, MacCheckbox, and MacDropdown.

  • Linux has a LinuxButton, LinuxCheckbox, and LinuxDropdown.

The Challenges

  1. Managing Families of Related Objects
    When switching between platforms, we need to ensure that all components belong to the same platform family. You don’t want of mix different UI components like WindowsButton with MacCheckbox.

  2. Extensibility for New Platforms
    Adding support for a new platform, such as Android, should be straightforward without breaking existing code.

  3. Decoupling Object Creation from Client Code
    The client code (your UI rendering logic) shouldn’t be tied to specific classes like WindowsButton or MacCheckbox.

What Do We Want Instead?

We need a solution that:

  • Centralizes Object Creation: Ensures components are created consistently for each platform.

  • Supports Families of Objects: All UI components for a specific platform (e.g., buttons, checkboxes) should be grouped logically.

  • Simplifies Adding New Platforms: Adding support for Android or other platforms should require minimal changes to the codebase.

This is where the Abstract Factory Pattern excels.

Let’s implement the Abstract Factory Pattern for our cross-platform UI toolkit.

Step 1: Define Abstract Product Interfaces

    interface Button {
      render(): void;
    }

    interface Checkbox {
      render(): void;
    }

Step 2: Implement Concrete Products

    class WindowsButton implements Button {
      render(): void {
        console.log("Rendering Windows Button");
      }
    }

    class MacButton implements Button {
      render(): void {
        console.log("Rendering Mac Button");
      }
    }

    class WindowsCheckbox implements Checkbox {
      render(): void {
        console.log("Rendering Windows Checkbox");
      }
    }

    class MacCheckbox implements Checkbox {
      render(): void {
        console.log("Rendering Mac Checkbox");
      }
    }

Step 3: Define Abstract Factory

    interface UIFactory {
      createButton(): Button;
      createCheckbox(): Checkbox;
    }

Step 4: Implement Concrete Factories

    class WindowsFactory implements UIFactory {
      createButton(): Button {
        return new WindowsButton();
      }

    createCheckbox(): Checkbox {
        return new WindowsCheckbox();
      }
    }

    class MacFactory implements UIFactory {
      createButton(): Button {
        return new MacButton();
      }
      createCheckbox(): Checkbox {
        return new MacCheckbox();
      }
    }

Step 5: Client Code

    function renderUI(factory: UIFactory): void {
      const button = factory.createButton();
      const checkbox = factory.createCheckbox();
      button.render();
      checkbox.render();
    }

Step 6: Using the Factories

    console.log("Rendering Windows UI:");
    renderUI(new WindowsFactory());

    console.log("\nRendering Mac UI:");
    renderUI(new MacFactory());

Output:

Rendering Windows UI:
Rendering Windows Button
Rendering Windows Checkbox

Rendering Mac UI::
Rendering Mac Button
Rendering Mac Checkbox




3.Real-Life Projects That Use the Abstract Factory

  1. Cross-Platform Frameworks
    Frameworks like Qt or Flutter use the Abstract Factory Pattern to render UI components across platforms like Windows, macOS, and Linux.

  2. Database Connection Managers
    Abstract factories can create database connections for different databases (e.g., MySQL, PostgreSQL, MongoDB), ensuring that related components like query builders and transactions work consistently.

  3. Theming Systems
    The Abstract Factory Pattern is used to create UI components for specific themes (e.g., light mode, dark mode).

Conclusion

The Abstract Factory Pattern is a versatile design pattern that simplifies managing families of related objects while promoting scalability and maintainability. It’s particularly useful in scenarios involving cross-platform development, theming, or any situation where object families must remain consistent.

In the next article of our Learn Design Patterns series, we’ll explore the Builder Pattern, which focuses on constructing complex objects step by step. Stay tuned, and keep learning!

Featured ones: