Observer Design Pattern – Usage and Example in PHP

This is another post regarding design patterns. This time it is observer design pattern which is helpful in developing system having plugin facility and subscription based services. I will present example in PHP for Observer design pattern which is taken from Aaron Saray's Professional PHP Design Patterns book on design pattern. This time again I have modified the code a little to best suit to the accuracy of the pattern (as far as I understand it).

Observer design pattern is a one-to-many dependency between objects so that when one object changes state, all dependency are notified and updated automatically. It helps in keeping design loosely coupled between objects that interact. - from Head First Design Patterns.

When a situation arises that a subject is monitored for its changes by many observers then we can use Observer Design pattern. A newspaper and its subscribers define such a relationship. Observer Design pattern is based on state change. As soon as an object changes its state, all the listed observers are notified of the changes. So, this way in newspaper example, it can be new news that has come. So, everyone subscribed to it will be notified. In this pattern, Observable or Subject does not and need not depends on what the observers will do after receiving state changes notification. It is up to observers what they will do with the message. At any time there can be zero or more observers can be registered. Subject class or observable does not bother about it. It just register observers for an event and notify for the event registered.

Suppose we have three person subscribed to a newspaper. How we would notify him of new news update? In general we prompt to write our code like this:

<?php
class newspaper {
	public function newNews() {
		$news = this->getNews();
		$personOne->update($newNews);
		$personTwo->update($newNews);
		$personThree->update($newNews);
	}
}
?>

By coding here we have no way to add or remove new subscriber. So, for solution, for better solution watch out for the way code implemented below. The below implemented code is from Aaron Saray's Professional PHP Design Patterns. That can tell you how the above code should be implemented.

UML for Observer Design Pattern:

I have found this image most suitable from flexscript.

This time, not only I have updated the code to make it most suitable for the Observer design pattern as I have learned, I have made the code separate in files so it helps you better understand the code and visualize it. The book code can be downloaded from here.

Observer Design Pattern in PHP:

FileName: observer1.php


<?php
// It is a subject class. It is observable class.
interface Subject {
	public function attachObserver($type, Observer $observer);
	//public function removeObserver();
	public function notifyObserver($type);
}
class CD implements Subject {
	public $title = '';
	public $band = '';
	private $_observers = array();
	public function __construct($title_, $band_) {
		$this->title = $title_;
		$this->band = $band_;
	}
	public function attachObserver ($type_, Observer $observer_) {
		$this->_observers[$type_][] = $observer_;
	}
	public function notifyObserver ($type_) {
		if (isset($this->_observers[$type_])) {
			foreach ($this->_observers[$type_] as $observer) {
				$observer->update($this); // passed the Observable object. So, observable can use it. Pull model!
				// If we have implemented like this, then Push Model
				// $observer->update(data1, data2); // Push Model
			}
		}
	}
	public function buy () {
		$this->notifyObserver('purchased');
	}
}

FileName:observable1.php


<?php
// This is observer class. It is watching for change on subject class.
// It will be notified whenever a change occurs in subject class (a CD class in our case).
// there can be many class like this which is watching for change( in CD class).
interface Observer {
	public function update(Subject $cd);
}
class buyCDObserver implements Observer {
	public function update (Subject $cd_) {
		$activity = "The CD named '{$cd_->title}'  by '$cd_->band' was just purchased.";
		echo $activity;
	}
}

FileName: usage1.php


<?php
// now we will see our code in action
require './observer1.php';
require './observable1.php';
$title 	= 'A CD title';
$band 	= 'A Rock Band';
// Subject got a life
$cd = new CD ($title, $band);
$observer = new buyCDObserver();
$cd->attachObserver ('purchased', $observer);
$cd->buy();
?>

In the example, as soon as CD is purchased, all observers of purchased type are notified of the state. The state change is new CD has been purchased.

I hope you find this guide as enjoyable to read as I did to create. Subscribe to feed or join me on Facebook for a regular update.

Comments are open for an year period. Please, write here on Facebook page.