The Observer pattern is a behavioral design pattern that allows objects to establish a one-to-many dependency relationship. In this pattern, an object, known as the subject or observable, maintains a list of dependents, known as observers, and notifies them automatically of any state changes. The observers can then react to these notifications and perform appropriate actions. The Observer pattern promotes loose coupling between the subject and observers, enabling a flexible and maintainable code structure.
In PHP, you can implement the Observer pattern using built-in language features or by creating custom classes.
Let's explore an example using custom classes:
// Subject interface defines the contract for the subject (observable) object.
interface Subject {
public function attach(Observer $observer);
public function detach(Observer $observer);
public function notify();
}
// Concrete subject class implements the subject interface.
class WeatherStation implements Subject {
private $temperature;
private $observers;
public function __construct() {
$this->observers = [];
}
public function attach(Observer $observer) {
$this->observers[] = $observer;
}
public function detach(Observer $observer) {
$index = array_search($observer, $this->observers);
if ($index !== false) {
unset($this->observers[$index]);
}
}
public function notify() {
foreach ($this->observers as $observer) {
$observer->update($this->temperature);
}
}
public function setTemperature($temperature) {
$this->temperature = $temperature;
$this->notify();
}
}
// Observer interface defines the contract for the observer objects.
interface Observer {
public function update($temperature);
}
// Concrete observer classes implement the observer interface.
class UserInterface implements Observer {
public function update($temperature) {
echo "Updating user interface. Current temperature: " . $temperature . " degrees Celsius.<br>";
}
}
class Logger implements Observer {
public function update($temperature) {
echo "Logging temperature: " . $temperature . " degrees Celsius.<br>";
}
}
In this example, we have a WeatherStation
class that acts as the subject. It implements the Subject
interface, which defines methods for attaching, detaching, and notifying observers. The subject maintains an array of observers and notifies them whenever the temperature changes.
We also have two observer classes: UserInterface
and Logger
. Both classes implement the Observer interface, which defines the update()
method for receiving updates from the subject.
To use the observer pattern, we can create instances of the subject and observer classes, and establish the dependency relationship by attaching observers to the subject:
//...
$weatherStation = new WeatherStation();
$userInterface = new UserInterface();
$logger = new Logger();
$weatherStation->attach($userInterface);
$weatherStation->attach($logger);
$weatherStation->setTemperature(25.5);
//...
In this code, we create an instance of the WeatherStation
class and two observer objects: UserInterface
and Logger
. We attach both observers to the weather station using the attach()
method. When we set the temperature using the setTemperature()
method, the weather station notifies all attached observers, and they react accordingly by updating the user interface and logging the temperature.
The Observer pattern allows for flexible and decoupled communication between subjects and observers. It enables dynamic addition and removal of observers without modifying the subject, promotes code reusability, and helps build systems that are easier to extend and maintain.