Software design patterns are tried and tested solutions to problems that developers commonly face while creating software. If you’d like an in-depth explanation of software design patterns and their benefits, do check out this post we did on the subject – What Are Software Design Patterns & An Introduction to Factory Design Pattern.
That said, software design patterns are not a one-size-fits-all solution. There are, in all, 23 basic types of software design pattern and each software development problem necessitates the use of one or more of them.
It’s one such pattern that we’re going to talk about here. Read on to know what is observer design pattern, its pros and cons, and when to use it.
What is Observer Design Pattern?
Observer pattern is classified under the behavioural type of software design patterns. Behavioural patterns deal with the communication between different objects of the classes.
The observer design pattern, as such, enables one object (also called an observable or subject) to communicate a change in its state to other objects (also called an observer or object) that are observing it. In other words, the subject alerts the objects observing it every time it changes.
Observer pattern ensures a clear separation between the subject and the observer objects. It lets you define the boundaries between various modules, which improves the maintainability and reusability of your software.
In this way, the observer pattern lets you notify other objects about the change in the subject’s state while ensuring a high level of collaboration, ease of use, and loose coupling.
Read More: Understanding Factory Method with a Factory Design Pattern Case Study
Let’s understand this with a simple real-world analogy. Say, you found a great website that sums up all the important news of the day via a newsletter. You liked the content and subscribe to this newsletter. You continue to enjoy the daily newsletters, until the day you don’t because of any number of reasons. So, you decide to withdraw your subscription to the website. Bear in mind that there are probably thousands of people subscribing or unsubscribing at the same time as you.
In software development, the news website and its users (i.e. you) constitute an observer design pattern. While the website is the subject here, the subscribers are the observers. So, every time the subject’s state changes, it broadcasts the same to its observers, who then go onto update themselves and display those changes.
A Case Study Example of Observer Design Pattern
Let’s take a real-life use case to understand how observer design pattern makes it easier to create a system where you can get a set of objects interested in the changes that are happening to another object.
Problem:
Assume you have two types of objects – ShareHolder and ShareMarket. The former wants to sell one unit when the share price drops by $10. Normally, the ShareHolder will do this by constantly checking the share price movement on the index. It’s obvious that such an approach will lead to a lot of time wastage and might even cause the ShareHolder to miss the moment when the share price does drop by $10.
Solution:
In this case, the observer design pattern is used to design a publisher and subscriber pattern, similar to the newsletter example we saw previously. Here, the ShareMarket is the object whose state the other object, ShareHolder, is interested in. As such, the former is the publisher and the latter, the subscriber.
The publisher will notify all its subscribers whenever its state changes. The subscriber(s) can then choose what to do with that information, i.e. they can either continue with the subscription or unsubscribe once their stated purpose is achieved.
This arrangement is perfectly illustrated by the below image,
Note – In the observer design pattern, all the subscribers have to implement the same interface and the publisher must communicate via that interface only.
As mentioned previously, the ShareHolder is the subscriber who will be notified by the publisher (ShareMarket) when the share price drops by $10. Once the subscriber achieves their intended goal of selling a share, they can unsubscribe from the publisher to avoid receiving unwanted notifications.
Applicability of Observer Design Pattern
Let’s look at how you can implement a PHP-based system where a change in the state of one object requires a change in the state of other objects. Note that PHP offers several inbuilt interfaces to implement an observer design pattern. The one featured below is a standard template.
SplSubject Interface
SplSubject Interface interface SplSubject { /** * Attach an SplObserve * @param SplObserver $observer * @return void */ public function attach (SplObserver $observer); /** * Detach an observer * @param SplObserver $observe * @return void */ public function detach (SplObserver $observer); /** * Notify an observer * @return void */ public function notify (); }
SplObserver Interface
interface SplObserver { /** * Receive update from subject * @param SplSubject $subject * @return void */ public function update (SplSubject $subject); }
Here, the attach() function allows us to register or link an observer (subscriber) to a subject (publisher). Similarly, detach() is used to unregister or unlink a publisher and a disinterested observer.
The notify() method communicates a change in state to all subscribed observers, following which the update() is called on each observer.
A Subject/Publisher Implementation
use SplSubject; use SplObserver; class Publisher implements SplSubject { /** * @var array */ protected $linkedList = array(); /** * @var array */ protected $observers = array(); /** * * @param string */ protected $name; /** * * @param string */ protected $event; public function __construct($name) { $this->name = $name; } /** * Associate an observer * * @param SplObserver $observer * @return Publisher; */ public function attach(SplObserver $observer) { $observerKey = spl_object_hash($observer); $this->observers[$observerKey] = $observer; $this->linkedList[$observerKey] = $observer->getPriority(); arsort($this->linkedList); } /** * @param SplObserver $observer * @return void */ public function detach(SplObserver $observer) { $observerKey = spl_object_hash($observer); unset($this->observers[$observerKey]); unset($this->linkedList[$observerKey]); } /** * @return void */ public function notify() { foreach ($this->linkedList as $key => $value) { $this->observers[$key]->update($this); } } /** * Set or update event * * @param $event * @return void */ public function setEvent($event) { $this->event = $event; $this->notify(); } /** * @return string */ public function getEvent() { return $this->event; } public function getSubscribers() { return $this->getSubscribers(); } }
Here, we define an attach() method so that an observer instance is accepted as an argument. And as we saw previously, the method lets you associate the observer with the observable, i.e. subject. Similarly, the detach() method is used to detach the two.
The notify() method loops through the linked list, acquires the subscriber’s key, uses it to locate the said observer, and then calls update() on that observer.
Note – The linked list is arranged in a way so that the highest priority observer gets alerted first.
The setEvent() function accepts the argument of an event you want to broadcast before calling notify(), which then calls update() in all observer objects.
An Observer/Subscriber Implementation
use SplObserver; use SplSubject; class Observer implements SplObserver { /** * @var string */ protected $name; /** * @var int */ protected $priority = 0; /** * Accepts observer name and priority, default to zero */ public function __construct($name, $priority=0) { $this->name =$name; $this->priority =$priority; } /** * Receive update from subject and print result * * @param SplSubject $publisher * @return void */ public function update(SplSubject $publisher){ print_r($this->name.': '. $publisher->getEvent(). PHP_EOL); } /** * Get observer priority * * @return int */ public function getPriority(){ return $this->priority; } }
Observer Design Pattern Usage
Here’s an observer pattern use case where you broadcast an event to your team via Zoom. Now, some of your team members are on vacation and only reachable through email. Additionally, you also want a live feed of this broadcast on the main screen in your office. This is how you can implement all of that with observer design pattern:
$noty = new Publisher('NotificationPublisher'); $email = new Observer('EmailObserver', 50); $zoom = new Observer('ZoomObserver', 10); $dashboard = new Observer('DashboardObserver',30); // Attach observers$noty->attach($email); $noty->attach($zoom); $noty->attach($dashboard);// Set event that will be broadcasted $noty->setEvent("Server LNX109 is going down");
The Output
EmailObserver: Server LNX109 is going down
DashboardObserver: Server LNX109 is going down
ZoomObserver: Server LNX109 is going down
What are the Pros and Cons of Observer Design Pattern?
Pros –
i) Observable (subject) and observers (objects) are loosely coupled. This lets you reuse the two independently of each other. For instance, you can make as many changes as you want to the observers without having to modify too many things.
ii) Makes your code maintainable, reusable, scalable and the development process faster and cheaper, especially if you hire dedicated resources for the task.
Cons –
i) If observer is wrongly implemented, it can increase complexity and cause unintended performance issues.
ii) It can lead to memory leaks if the observer fails to detach from the subject when it no longer wants to receive notifications, aka, the Lapsed Listener Problem.
When to Use Observer Design Pattern?
Your dedicated development team can consider using observer design pattern when,
i) the change in state of one object must be reflected in the state of another object while keeping the two objects loosely coupled
ii) the code needs to be enhanced in the future by adding new observers while keeping changes to the minimum.
Summing It Up
“Observer pattern defines a one-to-many dependency between objects so that when one object changes state, all of its dependents are notified and updated automatically” – Gang of Four
This aspect of observer design pattern makes it an ideal choice for use in eCommerce stores, news feeds, live chats, social media (now you know how notifications work on Twitter, Facebook, and YouTube). It provides an organized and proven design for applications where several objects are dependent on the state of one object.
As an IT business solution provider for almost 20 years, we’ve used observer design patterns to build robust and scalable software quickly. This has helped our clients save money and time while effectively responding to dynamic market conditions and user preferences. If your business is faced with a similar challenge, get in touch with our dedicated development team now.
Thank you for reading! If you liked this post, subscribe to our blog and get informative posts delivered straight to your inbox. We cover diverse topics on our blog including web and mobile development, data analytics, business intelligence, and eCommerce.
Digital Marketing Manager
Responsible for developing and managing web presence, Sarah has been associated with eLuminous Technologies for 7+ years. Strategic and innovative with a passion for Content Marketing and enhancing brand awareness. Administered all business marketing operations and advertisement campaigns that eventually increased web traffic. She works under the motto “Think like a Publisher, not a Marketer.”