Backend Development 7 min read

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

This article introduces four essential PHP design patterns—Singleton, Factory, Observer, and Adapter—explaining their purpose, providing complete code examples, and showing how they improve code maintainability, extensibility, and flexibility in backend development.

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; patterns provide proven solutions that help write more maintainable, extensible, and flexible code.

Singleton Pattern

The Singleton pattern ensures a class has only one instance. In PHP it can be implemented using static methods and properties.

<code>class Database {
    private static $instance;

    private function __construct() {
        // prevent external instantiation
    }

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

By making the constructor private, the class cannot be instantiated elsewhere; the getInstance method returns the sole instance, creating it on first call.

Factory Pattern

The Factory pattern creates objects based on given parameters, allowing different types to be instantiated through a single interface.

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

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

class Rectangle implements Shape {
    public function draw() {
        // draw a 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 supplied type.

Observer Pattern

The Observer pattern establishes a one‑to‑many dependency so that when a subject changes state, all its observers 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 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 (e.g., EmailNotifier ) whenever its name or email changes.

Adapter Pattern

The Adapter pattern converts one interface into another compatible one. In PHP, an adapter class can wrap an existing implementation to match a different interface.

<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 implements Json by internally using a CsvWriter to transform data.

Understanding and applying these design patterns—Singleton, Factory, Observer, and Adapter—enables PHP developers to write higher‑quality backend code that is easier to maintain, extend, and adapt to changing requirements.

Design Patternsbackend developmentsingletonAdapterFactoryObserver
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.