Observer Pattern
This lesson discusses the observer pattern in detail using a coding example.
We'll cover the following
What is the observer pattern? #
The observer pattern is a major behavioral design pattern. It allows objects (observers) that have subscribed to an event to wait for input and react to it when notified; meaning, they don’t have to continuously keep on checking whether the input has been provided or not. The main subject maintains a list of all the observers, and whenever the event occurs, it notifies the observers so they can update their states accordingly.
Let’s look at a real-life example that we can map to this pattern. Consider a website that posts interesting articles. Every day you visit the site to check for new articles and if there is none you revisit after some time/days. What if you get a subscription to the website instead? Once you have the subscription, you’ll get notified every time a new article is posted. So now, instead of checking the site every few hours, you just wait for the notification for the new article.
Example #
Let’s look at a coding example to understand the implementation of the observer pattern.
class Subject{constructor(){this.observerList = []this.newArticlePosted = falsethis.articleName = null}subscribe(observer){this.observerList.push(observer)}unsubscribe(observer){this.observerList = this.observerList.filter(obs => obs !== observer)}notify(){if(this.newArticlePosted){this.observerList.forEach(subscriber => subscriber.update())}else{return}}getUpdate(){return this.articleName}postNewArticle(articleName){this.articleName = articleNamethis.newArticlePosted = truethis.notify()}}class Observer{constructor(){this.subject = new Subject()}update(){if(subject.getUpdate() == null){console.log("No new article")}else{console.log(`The new article ${subject.getUpdate()} is posted`)}}setSubject(subject){this.subject = subject}}var subject = new Subject()var observer = new Observer()observer.setSubject(subject)subject.subscribe(observer)observer.update()subject.postNewArticle("Dark matter")
Explanation
In this example, we have the Subject
class that stores the list of all observers and notifies them if a new article gets posted on the website.
class Subject{
constructor(){
this.observerList = []
this.newArticlePosted = false
this.articleName = null
}
//code..
}
The constructor
initializes the list observerList
that stores all the observers. It has two other properties: newArticlePosted
(boolean variable to check whether a new article has been posted or not) and articleName
(the name of the article).
It also defines the subscribe
and unsubscribe
functions to register or remove an observer from the subscription.
subscribe(observer){
this.observerList.push(observer)
}
unsubscribe(observer){
this.observerList = this.observerList.filter(obs => obs !== observer)
}
It also has the getUpdate
function that returns the name of the new article posted.
getUpdate(){
return this.articleName
}
How is the new article posted? Using the postNewArticle
function.
postNewArticle(articleName){
this.articleName = articleName
this.newArticlePosted = true
this.notify()
}
When a new article is posted, its name is set, the variable newArticlePosted
is set to true
, and the observer is notified about it by invoking the notify
function.
notify(){
if(this.newArticlePosted){
this.observerList.forEach(subscriber => subscriber.update())
}
else{
return null
}
}
The notify
function checks if a new article is posted; if so, it sends the update to each subscriber in the list; else, it returns.
The Observer
class is defined as follows:
class Observer{
constructor(){
this.subject = new Subject()
}
//codee..
setSubject(subject){
this.subject = subject
}
}
The constructor
initiates an instance of Subject
and sets it using setSubject
. The funtion accepts a Subject
instance and sets it as the subject
for the observer.
The Observer
also has the update
function.
update(){
if(subject.getUpdate() == null){
console.log("No new article")
}else{
console.log(`The new article ${subject.getUpdate()} is posted`)
}
}
This function is invoked by the Subject
to notify the observer about the new article getting posted. Hence, it checks for an update; if a new article is found, it displays the notification for it else it returns No new article
.
When to use the observer pattern?
The observer pattern can be used:
-
To improve code management by breaking down large applications into a system of loosely coupled objects.
-
To provide greater flexibility by enabling a dynamic relationship between observers and subscribers, otherwise, not possible due to tight coupling.
-
To improve communication between different parts of the application.
-
To create a one-to-many dependency between objects that are loosely coupled.
Now that you know what the observer pattern is, it’s time to implement it!