Exploring Design Patterns in PHP 8: Strategy, Observer and Decorator

Exploring Design Patterns in PHP 8: Strategy, Observer and Decorator

On28th Oct 2024, 2024-12-20T09:28:43+05:30 ByKarthik Kumar D K | read
Listen Pause Resume Stop

Design patterns are essential tools for software developers, providing proven solutions to common problems. In PHP 8, leveraging design patterns can lead to more maintainable, scalable and flexible code.

This article will explore three key design patterns: Strategy, Observer and Decorator. We will delve into their principles and provide practical examples to illustrate how they can be implemented in PHP 8.

1. Strategy Pattern

The Strategy Pattern enables the selection of an algorithm at runtime. By defining a family of algorithms, encapsulating each one and making them interchangeable, you can alter the algorithm used by a context object without modifying its code.

Step 1: Define the Strategy Interface

This interface declares a method that will be implemented by concrete strategies.

interface SortingStrategy {

    public function sort(array $data): array;

}

Step 2: Create Concrete Strategies

Implement different sorting algorithms as concrete strategies.

class QuickSort implements SortingStrategy {

    public function sort(array $data): array {

        sort($data); // Simplified for illustration

        return $data;

    }

}

class BubbleSort implements SortingStrategy {

    public function sort(array $data): array {

        // Implement bubble sort logic here

        return $data; // Simplified for illustration

    }

}

Step 3: Create the Context

The context class uses a strategy to execute the algorithm.

class Sorter {

    private SortingStrategy $strategy;

    public function __construct(SortingStrategy $strategy) {

        $this->strategy = $strategy;

    }

    public function setStrategy(SortingStrategy $strategy): void {

        $this->strategy = $strategy;

    }

    public function sortData(array $data): array {

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

    }

}

Usage Example

$data = [3, 2, 1];

$sorter = new Sorter(new QuickSort());

print_r($sorter->sortData($data)); // Uses QuickSort

$sorter->setStrategy(new BubbleSort());

print_r($sorter->sortData($data)); // Now uses BubbleSort

2. Observer Pattern

The Observer Pattern defines a one-to-many dependency between objects, allowing one object (the subject) to notify others (observers) about state changes. This pattern is particularly useful in event handling and notification systems.

Step 1: Define Subject and Observer Interfaces

interface Subject {

    public function attach(Observer $observer): void;

    public function detach(Observer $observer): void;

    public function notify(): void;

}

interface Observer {

    public function update(string $event): void;

}

Step 2: Create a Concrete Subject

The subject maintains a list of observers and notifies them of any changes.

class NewsAgency implements Subject {

    private array $observers = [];

    public function attach(Observer $observer): void {

        $this->observers[] = $observer;

    }

    public function detach(Observer $observer): void {

        $this->observers = array_filter($this->observers, fn($o) => $o !== $observer);

    }

    public function notify(): void {

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

            $observer->update("New news available!");

        }

    }

}

Step 3: Create Concrete Observers

Observers implement the update method to receive notifications.

class NewsSubscriber implements Observer {

    public function update(string $event): void {

        echo "Received update: $event\n";

    }

}

Usage Example

$agency = new NewsAgency();

$subscriber = new NewsSubscriber();

$agency->attach($subscriber);

$agency->notify(); // Outputs: Received update: New news available!

3. Decorator Pattern

The Decorator Pattern allows you to dynamically add behavior to objects. This is achieved by wrapping an object with a decorator class, enabling enhanced functionality without altering the original class.

Step 1: Define the Component Interface

interface Coffee {

    public function cost(): float;

}

Step 2: Create a Concrete Component

Implement the core functionality in a concrete class.

class SimpleCoffee implements Coffee {

    public function cost(): float {

        return 2.00;

    }

}

Step 3: Create the Decorator Base Class

The base class for decorators should implement the same interface and hold a reference to a Coffee object.

abstract class CoffeeDecorator implements Coffee {

    protected Coffee $coffee;

    public function __construct(Coffee $coffee) {

        $this->coffee = $coffee;

    }

    public function cost(): float {

        return $this->coffee->cost();

    }

}

Step 4: Create Concrete Decorators

Implement decorators that extend the functionality of the original object.

class MilkDecorator extends CoffeeDecorator {

    public function cost(): float {

        return parent::cost() + 0.50; // Adds milk cost

    }

}

class SugarDecorator extends CoffeeDecorator {

    public function cost(): float {

        return parent::cost() + 0.25; // Adds sugar cost

    }

}

Usage Example

$coffee = new SimpleCoffee();

echo "Cost of simple coffee: " . $coffee->cost() . "\n";

$milkCoffee = new MilkDecorator($coffee);

echo "Cost of coffee with milk: " . $milkCoffee->cost() . "\n";

$sweetMilkCoffee = new SugarDecorator($milkCoffee);

echo "Cost of coffee with milk and sugar: " . $sweetMilkCoffee->cost() . "\n";

Conclusion

In this article, we explored three essential design patterns: Strategy, Observer and Decorator, using PHP 8. Each pattern provides unique advantages that can significantly enhance your codebase. By applying these patterns, you can create a more modular and maintainable system, allowing for easier updates and modifications as your application evolves. Embracing design patterns is a step toward becoming a proficient PHP developer, leading to cleaner and more efficient code.

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