The Observer Pattern - Design Patterns
Before we start, you might ask:
What is a design pattern?
Design pattern is a general solution to particular problem that is occurring commonly. However this is not an already implemented source code (you’ll have to do that yourself). It is not an already finished design either. You can incorporate design patterns into your application design.
It formalizes best practices and describes interactions between objects and classes. Basically it is a template for how to solve a problem.
If you want to get a better description of what a design pattern is, you can read about it on Wikipedia
Observer pattern
It is a one-to-many push type design pattern, in which an object (“Subject”) maintains a list of dependants (“observers”). Once the subject changes state, it automatically notifies each observer with its new state.
You can think of it as a mailing list. Mailing list is the subject, you attach to it by sending in your e-mail address. But there can be many subscribers - Observer pattern does not limit the number of observers.
When there is a new email, the state has changed and the server emails it to each of the subscribers, including you!
Example
Let’s build our own simple application that uses the Observer pattern. In this example we’re going to use PHP.
There will be at least 2 classes - one for the Subject, one for the Observer.
The Subject will have to have at least these three methods:
Attach
- a method that the observers will use to registerDetach
- observers may want to unregisterNotify
- This will change subject’s state
As for the Observer, we can get away with this single method:
Notify
- Notification method, which will be called by the subject
Ok, let’s start coding! Let’s start by creating a Subject
class:
<?php
// Subject.php
class Subject {
private $observers = array(); // We will store observers here
public function attach($observer) {
if(!in_array($observer, $this->observers)) { // Make sure we don't add an observer twice
$this->observers[] = $observer; // Add the observer
return true;
} else {
return false; // Observer was not added
}
}
public function detach($observer) {
if(!in_array($observer, $this->observers)) { // Make sure the observer is registered
return false;
} else {
$key = array_search($observer, $this->observers); // Find observer's key
unset($this->observers[$key]); // Remove the observer
$this->observers = array_values($this->observers); // Reindex the observer array, as unset leaves a gap
return true;
}
}
public function notify($message) {
foreach($this->observers as $observer) { // Notify each observer
$observer->notify($message); // Dispatch the message to each observer
}
}
};
Ok, we’ve implemented our Subject
class. Observers
will register through attach
method and unregister through detach
method. Notifications will be sent with notify
method.
Now let’s build our Observer
class:
<?php
// Observer.php
class Observer {
public function notify($message) {
echo "I have received a message: \r\n";
var_dump($message); // Just print out any information it may contain: strings, numbers, objects...
echo "END OF MESSAGE\r\n";
}
};
Our Observer
class only needs notify
method, which will output all received messages.
And lastly, let’s create our demo program that makes use of these classes:
<?php
// main.php
require_once('Subject.php');
require_once('Observer.php');
$subject = new Subject(); // Create a Subject
// Let's try to change state. It should not output anything as it doesn't have any observers registered
$subject->notify('This shall not be read!');
// Let's create an Observer, register it and send another notification
$observer = new Observer(); // Create an Observer
$subject->attach($observer); // Register Observer to the Subject
$subject->notify('Can you see me?'); // Send notification to the Observer
If we run this, we should see Can you see me?
text. If you do - good work! Now you know the Observer pattern.
I’ve created a Github repository with complete code from this article.
Subscribe via RSS