Hello developers, With this blog I am starting a series on the basic and essential design patterns that every developer should know. Design patterns in simple terms are pre-made solutions to an existing problem that a developer may face! (P.S. Dont judge me, that is the easiest explanation that I can give!)
What problem does the Observer pattern solve?
Hashnode or any newsletter-based services are a perfect example. Lets say you subscribe to my Hashnode newsletter, You will receive a notification whenever I upload a blog. If you feel that you no longer need to get notifications from my newsletter you can unsubscribe as well. So this is exactly the problem that the Observer pattern is solving. Lets continue with this newsletter example itself in this blog.
A detailed example of the Observer pattern
The Observer pattern is also known as the Publisher / Subscriber (Pub/Sub) pattern where Hashnode (on behalf of the blogger) is the Publisher and you, subscribing to the newsletter, the subscriber.
Here, The publisher keeps track of the subscribers, If anyone wants to subscribe, they can subscribe themselves via the publisher and the same goes with unsubscribing someone. And, as long as the users are subscribed to the newsletter, they will receive the notification else they wont. It is that simple!
Lets look at some code!
I am explaining it in TypeScript but design patterns are not specific to a programming language.
First, lets define the Publisher
and Subscriber
interfaces
interface Subscriber {
update(message: string): void; // gets updated or notified
}
interface Publisher {
subscribe(subscriber: Subscriber): void; // subscribes the user
unsubscribe(subscriber: Subscriber): void; // unsubscribes the user
notify(blogName: string): void; // sends notification to users
}
The code is pretty straightforward. Now lets create Hashnode and the User classes
class Hashnode implements Publisher {
private observers: Subscriber[] = []; // tracks the subscribers
subscribe(observer: Subscriber) {
this.observers.push(observer); // adds user into the subscriber array
}
unsubscribe(observer: Subscriber) {
const index = this.observers.indexOf(observer);
if (index !== -1) {
this.observers.splice(index, 1); // removes the user
}
}
notify(blogName: string) {
for (const observer of this.observers) {
observer.update(blogName); // updates the subscriber
}
}
}
class User implements Subscriber {
private name: string;
constructor(name: string) {
this.name = name;
}
update(message: string) {
// just a simple console log for this example
console.log(`${this.name} received message: ${message}`);
}
}
Now lets try out our design pattern! First, lets create our publisher and subscribers
const hashnode = new Hashnode();
const priya = new User('Priya');
const karan = new User('Karan');
const mani = new User('Mani');
const komal = new User('Komal');
const aishwarya = new User('Aishwarya');
Now lets subscribe all the users to hashnode
.
hashnode.subscribe(priya);
hashnode.subscribe(karan);
hashnode.subscribe(mani);
hashnode.subscribe(komal);
hashnode.subscribe(aishwarya);
Lets publish our first blog
hashnode.notify('New blog on clean code');
Now If we execute, this will be the result. You can see that all 5 users got notified!
Now one user, Karan decides to unsubscribe from the newsletter.
hashnode.unsubscribe(karan);
And another blog is getting published.
hashnode.notify('New blog on Observer pattern');
Now If we execute the code the output will be like this.
As you can see, Karan didnt get notified because he unsubscribed from the newsletter.
Conclusion
Thats it, This is the observer pattern and it is used in a lot of places. There are real services out there like RabbitMQ, Google Clouds Pub/Sub which provides services that are tailored for this use case. So knowing about how these models work will be beneficial as a developer. Stay tuned for the next blog!
Top comments (0)