CHAPTER 4 – Observer Pattern

4.4.4 Observer Pattern PHP applications, usually manipulate data. In many cases, changes to one piece of data can affect many different parts of your application's code. For example, the price of each product item displayed on an e-commerce site in the customer's local currency is affected by the current exchange rate. Now, assume that each product item is represented by a PHP object that most likely originates from a database; the exchange rate itself is most probably being taken from a different source and is not part of the item's database entry. Let's also assume that each such object has a display() method that outputs the HTML relevant to this product. The observer pattern allows for objects to register on certain events and/or data, and when such an event or change in data occurs, it is automati- cally notified. In this way, you could develop the product item to be an observer on the currency exchange rate, and before printing out the list of items, you could trigger an event that updates all the registered objects with the correct rate. Doing so gives the objects a chance to update themselves and take the new data into account in their display() method. Usually, the observer pattern is implemented using an interface called Observer, which the class that is interested in acting as an observer must implement. For example: interface Observer { function notify($obj); } An object that wants to be "observable" usually has a register method that allows the Observer object to register itself. For example, the following might be our exchange rate class: class ExchangeRate { static private $instance = NULL; private $observers = array(); private $exchange_rate; private function ExchangeRate() { } static public function getInstance() { if (self::$instance == NULL) { self::$instance = new ExchangeRate(); } return self::$instance; } public function getExchangeRate() { return $this->$exchange_rate; } public function setExchangeRate($new_rate) { $this->$exchange_rate = $new_rate; $this->notifyObservers(); } public function registerObserver($obj) { $this->observers[] = $obj; } function notifyObservers() { foreach($this->observers as $obj) { $obj->notify($this); } } } class ProductItem implements Observer { public function __construct() { ExchangeRate::getInstance()->registerObserver($this); } public function notify($obj) { if ($obj instanceof ExchangeRate) { // Update exchange rate data print "Received update!n"; } } } $product1 = new ProductItem(); $product2 = new ProductItem(); ExchangeRate::getInstance()->setExchangeRate(4.5); This code prints Received update! Received update! Although the example isn't complete (the ProductItem class doesn't do anything useful), when the last line executes (the setExchangeRate() method), both $product1 and $product2 are notified via their notify() methods with the new exchange rate value, allowing them to recalculate their cost. This pattern can be used in many cases; specifically in web development, it can be used to create an infrastructure of objects representing data that might be affected by cookies, GET, POST, and other input variables.

Post Comment
Login to post comments