Backend Development 7 min read

Common Design Patterns in PHP: Singleton, Factory, Observer, and Adapter

This article introduces four essential design patterns—Singleton, Factory, Observer, and Adapter—explaining their concepts and providing complete PHP code examples to demonstrate how each pattern can be implemented to create maintainable, extensible, and flexible applications.

php中文网 Courses
php中文网 Courses
php中文网 Courses
Common Design Patterns in PHP: Singleton, Factory, Observer, and Adapter

In advanced PHP development, understanding common design patterns is a key skill. Design patterns provide proven solutions to specific problems, helping us write code that is easier to maintain, extend, and adapt.

Singleton Pattern

The Singleton pattern ensures a class has only one instance. In PHP, this can be achieved using static methods and variables.

<code>class Database {
    private static $instance;

    private function __construct() {
        // Prevent direct instantiation
    }

    public static function getInstance() {
        if (!isset(self::$instance)) {
            self::$instance = new Database();
        }
        return self::$instance;
    }
    // ...
}</code>

By making the constructor private, we prevent external instantiation. The getInstance method returns the single instance, creating it if it does not yet exist.

Factory Pattern

The Factory pattern creates objects based on supplied parameters. A factory class can encapsulate the creation logic.

<code>interface Shape {
    public function draw();
}

class Circle implements Shape {
    public function draw() {
        // draw circle
    }
}

class Rectangle implements Shape {
    public function draw() {
        // draw rectangle
    }
}

class ShapeFactory {
    public static function create($type) {
        if ($type == 'circle') {
            return new Circle();
        } else if ($type == 'rectangle') {
            return new Rectangle();
        } else {
            throw new Exception('Invalid shape type.');
        }
    }
}

// Usage
$circle = ShapeFactory::create('circle');
$rectangle = ShapeFactory::create('rectangle');
</code>

The example defines two shape classes, Circle and Rectangle , and a ShapeFactory that creates the appropriate object based on the given type.

Observer Pattern

The Observer pattern establishes a one‑to‑many dependency so that when an object changes state, all its dependents are notified. PHP’s SplSubject and SplObserver interfaces facilitate this.

<code>class User implements SplSubject {
    private $name;
    private $email;
    private $observers;

    public function __construct($name, $email) {
        $this->name = $name;
        $this->email = $email;
        $this->observers = new SplObjectStorage();
    }

    public function attach(SplObserver $observer) {
        $this->observers->attach($observer);
    }

    public function detach(SplObserver $observer) {
        $this->observers->detach($observer);
    }

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

    public function setName($name) {
        $this->name = $name;
        $this->notify();
    }

    public function setEmail($email) {
        $this->email = $email;
        $this->notify();
    }
    // ...
}

class EmailNotifier implements SplObserver {
    public function update(SplSubject $subject) {
        // Send email notification about name/email change
    }
}

// Create user and attach observer
$user = new User('John Doe', '[email protected]');
$user->attach(new EmailNotifier());

// Changing state triggers notifications
$user->setName('Jane Doe');
$user->setEmail('[email protected]');
</code>

The User class implements SplSubject and notifies attached observers when its name or email changes. The EmailNotifier class implements SplObserver to react to those changes.

Adapter Pattern

The Adapter pattern converts one interface into another compatible one. In PHP, an adapter class can bridge between different data format writers.

<code>interface Csv {
    public function outputCsv($data);
}

class CsvWriter implements Csv {
    public function outputCsv($data) {
        // output CSV
    }
}

interface Json {
    public function outputJson($data);
}

class JsonWriter implements Json {
    public function outputJson($data) {
        // output JSON
    }
}

class CsvToJsonAdapter implements Json {
    private $csvWriter;

    public function __construct(Csv $csvWriter) {
        $this->csvWriter = $csvWriter;
    }

    public function outputJson($data) {
        // Convert CSV data to JSON
        $csvData = implode(',', $data);
        $json = json_encode($csvData);
        return $json;
    }
}

// Usage
$csvWriter = new CsvWriter();
$jsonWriter = new CsvToJsonAdapter($csvWriter);
</code>

The example defines Csv and Json interfaces, concrete writers for each format, and a CsvToJsonAdapter that adapts a CSV writer to the JSON interface by converting data internally.

Understanding and applying these design patterns—Singleton, Factory, Observer, and Adapter—helps PHP developers write code that is more maintainable, extensible, and flexible.

design patternsPHPsingletonadapterFactoryObserver
php中文网 Courses
Written by

php中文网 Courses

php中文网's platform for the latest courses and technical articles, helping PHP learners advance quickly.

0 followers
Reader feedback

How this landed with the community

login Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.