Abstract Factory Design Pattern in PHP

1. Definition

The Abstract Factory Design Pattern provides an interface for creating families of related or dependent objects without specifying their concrete classes.

2. Problem Statement

Imagine you're designing a UI library that has to be compatible with multiple operating systems. Each UI element (like buttons, and checkboxes) might have different implementations for different OS. If you were to create each of these elements individually, your code would become cluttered with complex conditionals to determine the OS and instantiate the right class.

3. Solution

The Abstract Factory pattern allows you to define an interface for creating families of related objects without specifying the concrete classes. For each OS, you can have a factory that produces all the UI elements suited for that OS.

4. Real-World Use Cases

1. Creating a UI library that can work across different OS.

2. E-commerce platforms providing different product sets based on user membership level.

5. Implementation Steps

1. Define abstract factories and product interfaces.

2. Implement concrete products for each family.

3. Implement concrete factories for each family.

4. Use the concrete factory to instantiate the family of products.

6. Implementation in PHP

<?php
// Step 1: Define abstract factories and product interfaces
interface GUIFactory {
    public function createButton();
    public function createCheckbox();
}
interface Button {
    public function render();
}
interface Checkbox {
    public function check();
}
// Step 2: Implement concrete products for each family
class WindowsButton implements Button {
    public function render() {
        return "Windows Button Rendered!";
    }
}
class WindowsCheckbox implements Checkbox {
    public function check() {
        return "Windows Checkbox Checked!";
    }
}
class LinuxButton implements Button {
    public function render() {
        return "Linux Button Rendered!";
    }
}
class LinuxCheckbox implements Checkbox {
    public function check() {
        return "Linux Checkbox Checked!";
    }
}
// Step 3: Implement concrete factories for each family
class WindowsFactory implements GUIFactory {
    public function createButton() {
        return new WindowsButton();
    }
    public function createCheckbox() {
        return new WindowsCheckbox();
    }
}
class LinuxFactory implements GUIFactory {
    public function createButton() {
        return new LinuxButton();
    }
    public function createCheckbox() {
        return new LinuxCheckbox();
    }
}
// Client code
$factory = new WindowsFactory();
$button = $factory->createButton();
$checkbox = $factory->createCheckbox();
echo $button->render() . PHP_EOL;
echo $checkbox->check();
?>

Output:

Windows Button Rendered!
Windows Checkbox Checked!

Explanation:

We started by defining interfaces for both the Abstract Factory (GUIFactory) and the products (Button and Checkbox). Then, we created concrete implementations for each product for both Windows and Linux.

The concrete factories (WindowsFactory and LinuxFactory) then implement the creation methods specified in the GUIFactory interface.

In the client code, we used the WindowsFactory to produce a button and a checkbox suited for Windows. The pattern ensures that the products created are consistent with each other, hence a WindowsFactory would never create a LinuxButton.

7. When to use?

Use the Abstract Factory Pattern when:

1. The system needs to remain independent from how its objects are created, composed, and represented.

2. The system should be configured with multiple families of products.

3. Products from a family are designed to work together, and you need to enforce this constraint.


Comments