When and How to Use Each Design Pattern in PHP

When and How to Use Each Design Pattern in PHP

On4th Nov 2024, 2024-12-04T09:52:41+05:30 ByKarthik Kumar D K | read
Listen Pause Resume Stop

Design patterns are proven solutions to common problems in software design. In PHP 8, these patterns can enhance code readability, maintainability and scalability.

In this article, we’ll explore some of the most common design patterns, when to use them and how to implement them in PHP 8.

1. Singleton Pattern

When to Use

  • Use the Singleton pattern when you need to ensure that a class has only one instance and provide a global point of access to it.
  • This is particularly useful for managing shared resources, such as database connections or configuration settings.

How to Implement

class Singleton {

    private static ?Singleton $instance = null;

    private function __construct() {}

    public static function getInstance(): Singleton {

        if (self::$instance === null) {

            self::$instance = new Singleton();

        }

        return self::$instance;

    }

}

// Usage

$singleton = Singleton::getInstance();

2. Factory Pattern

When to Use

  • The Factory pattern is beneficial when you need to create objects without specifying the exact class of the object that will be created.
  • This is ideal for scenarios where you have a common interface but multiple implementations.

How to Implement

interface Shape {

    public function draw(): void;

}

class Circle implements Shape {

    public function draw(): void {

        echo "Drawing a Circle\n";

    }

}

class Square implements Shape {

    public function draw(): void {

        echo "Drawing a Square\n";

    }

}

class ShapeFactory {

    public static function createShape(string $type): Shape {

        return match($type) {

            'circle' => new Circle(),

            'square' => new Square(),

            default => throw new InvalidArgumentException("Invalid shape type"),

        };

    }

}

// Usage

$shape = ShapeFactory::createShape('circle');

$shape->draw();

3. Observer Pattern

When to Use

  • The Observer pattern is useful when you have one-to-many relationships between objects.
  • When one object changes its state, all its dependents should be notified and updated automatically, which is common in event-driven systems.

How to Implement

interface Observer {

    public function update(string $event): void;

}

class EventObserver implements Observer {

    public function update(string $event): void {

        echo "Received event: $event\n";

    }

}

class EventSource {

    private array $observers = [];

    public function attach(Observer $observer): void {

        $this->observers[] = $observer;

    }

    public function notify(string $event): void {

        foreach ($this->observers as $observer) {

            $observer->update($event);

        }

    }

}

// Usage

$eventSource = new EventSource();

$observer = new EventObserver();

$eventSource->attach($observer);

$eventSource->notify('Event 1');

4. Strategy Pattern

When to Use

  • Use the Strategy pattern when you want to define a family of algorithms, encapsulate each one and make them interchangeable.
  • This pattern lets the algorithm vary independently from clients that use it.

How to Implement

interface SortStrategy {

    public function sort(array $data): array;

}

class QuickSort implements SortStrategy {

    public function sort(array $data): array {

        // Implement quick sort algorithm

        return $data; // Placeholder

    }

}

class MergeSort implements SortStrategy {

    public function sort(array $data): array {

        // Implement merge sort algorithm

        return $data; // Placeholder

    }

}

class SortContext {

    private SortStrategy $strategy;

    public function __construct(SortStrategy $strategy) {

        $this->strategy = $strategy;

    }

    public function sortData(array $data): array {

        return $this->strategy->sort($data);

    }

}

// Usage

$data = [5, 3, 8, 1];

$context = new SortContext(new QuickSort());

$sortedData = $context->sortData($data);

5. Command Pattern

When to Use

  • The Command pattern is useful when you want to parameterize objects with operations, queue requests and support undoable operations.
  • This is often used in GUI applications.

How to Implement

interface Command {

    public function execute(): void;

}

class Light {

    public function turnOn(): void {

        echo "Light is ON\n";

    }

    public function turnOff(): void {

        echo "Light is OFF\n";

    }

}

class TurnOnCommand implements Command {

    private Light $light;

    public function __construct(Light $light) {

        $this->light = $light;

    }

    public function execute(): void {

        $this->light->turnOn();

    }

}

class TurnOffCommand implements Command {

    private Light $light;

    public function __construct(Light $light) {

        $this->light = $light;

    }

    public function execute(): void {

        $this->light->turnOff();

    }

}

// Usage

$light = new Light();

$turnOn = new TurnOnCommand($light);

$turnOff = new TurnOffCommand($light);

$turnOn->execute();

$turnOff->execute();

Conclusion

Understanding design patterns and knowing when and how to use them in PHP 8 can significantly improve your software architecture. By applying these patterns appropriately, you can create cleaner, more maintainable and flexible code. As you continue to work with PHP, consider these patterns as tools in your development toolbox, enabling you to tackle complex problems with elegant solutions.

Thanks for reading the article, for more Science & Technology related articles read and subscribe to peoples blog articles.

Labels


Related Articles

Recent Articles

Recent Quick Read

Recent Great People

We Need Your Consent
By clicking “Accept Cookies”, you agree to the storing of cookies on your device to enhance your site navigation experience.
I Accept Cookies