
PHP Design Patterns: Practical Examples and Best Practices
Table of Contents
- Singleton Pattern
- Factory Pattern
- Observer Pattern
- Strategy Pattern
- Conclusion
- 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.
