Table of Contents

  1. Singleton Pattern
  2. Factory Pattern
  3. Observer Pattern
  4. Strategy Pattern
  5. Conclusion
  6. Learn more with useful resources

Singleton Pattern

The Singleton Pattern ensures that a class has only one instance and provides a global point of access to it. This is particularly useful for managing shared resources like database connections.

Example

class Database {
    private static $instance = null;
    private $connection;

    private function __construct() {
        $this->connection = new PDO('mysql:host=localhost;dbname=test', 'user', 'password');
    }

    public static function getInstance() {
        if (self::$instance === null) {
            self::$instance = new Database();
        }
        return self::$instance;
    }

    public function getConnection() {
        return $this->connection;
    }
}

// Usage
$db = Database::getInstance()->getConnection();

Factory Pattern

The Factory Pattern provides a way to create objects without specifying the exact class of the object that will be created. This enhances flexibility and reduces dependencies.

Example

interface Shape {
    public function draw();
}

class Circle implements Shape {
    public function draw() {
        echo "Drawing a Circle\n";
    }
}

class Square implements Shape {
    public function draw() {
        echo "Drawing a Square\n";
    }
}

class ShapeFactory {
    public static function createShape($type) {
        switch ($type) {
            case 'circle':
                return new Circle();
            case 'square':
                return new Square();
            default:
                throw new Exception("Shape not recognized.");
        }
    }
}

// Usage
$shape = ShapeFactory::createShape('circle');
$shape->draw();

Observer Pattern

The Observer Pattern defines a one-to-many dependency between objects, allowing one object (the subject) to notify multiple observers of state changes. This is useful in event-driven programming.

Example

class Subject {
    private $observers = [];

    public function attach($observer) {
        $this->observers[] = $observer;
    }

    public function notify() {
        foreach ($this->observers as $observer) {
            $observer->update();
        }
    }
}

class Observer {
    public function update() {
        echo "Observer notified\n";
    }
}

// Usage
$subject = new Subject();
$observer1 = new Observer();
$observer2 = new Observer();

$subject->attach($observer1);
$subject->attach($observer2);
$subject->notify();

Strategy Pattern

The Strategy Pattern allows selecting an algorithm's behavior at runtime. It defines a family of algorithms, encapsulates each one, and makes them interchangeable.

Example

interface PaymentStrategy {
    public function pay($amount);
}

class CreditCardPayment implements PaymentStrategy {
    public function pay($amount) {
        echo "Paid $amount using Credit Card\n";
    }
}

class PayPalPayment implements PaymentStrategy {
    public function pay($amount) {
        echo "Paid $amount using PayPal\n";
    }
}

class ShoppingCart {
    private $paymentStrategy;

    public function setPaymentStrategy(PaymentStrategy $strategy) {
        $this->paymentStrategy = $strategy;
    }

    public function checkout($amount) {
        $this->paymentStrategy->pay($amount);
    }
}

// Usage
$cart = new ShoppingCart();
$cart->setPaymentStrategy(new CreditCardPayment());
$cart->checkout(100);

$cart->setPaymentStrategy(new PayPalPayment());
$cart->checkout(200);

Conclusion

Understanding and implementing design patterns in PHP can significantly improve the structure and maintainability of your code. The examples provided illustrate how to apply the Singleton, Factory, Observer, and Strategy patterns effectively. By incorporating these patterns into your development practices, you can create more robust and scalable applications.

Learn more with useful resources