DEV Community

Kumar Ayush
Kumar Ayush

Posted on • Edited on

System Design : Observer Design Patterns

Welcome to Day 2 of my System Design Learning Series! Today, let's dive into Design Patterns, Observer Pattern.
๐Ÿ“Œ Use Case: Payment methods in e-commerce (Credit Card, PayPal, UPI).
๐Ÿ”น Observer Design Pattern (Brief Overview)
The Observer Pattern establishes a one-to-many dependency between objects, so when one object (Observable) changes, all dependent objects (Observers) are notified.
๐Ÿ“Œ Use Case: Notification systems, event listeners, stock price updates.
๐Ÿ” Deep Dive: Observer Pattern โ€“ Walmart SDE Interview Question
โ“ Implement a notify function to notify all subscribers when an event occurs.
๐Ÿ’ก Solution:
1๏ธโƒฃ Define an Observable (Publisher) that maintains a list of observers.
2๏ธโƒฃ Implement attach, detach, and notify methods.
3๏ธโƒฃ Product extends Observable : Whenever the product properties changes, all observers get updated.
4๏ธโƒฃ The Observers (Subscribers) react when notified.

Hereโ€™s the Observer Pattern implementation for the problem using javascriptโ€‹:

class Observable {
 constructor() { 
 this.observers = []; //maintaining list of observer
 }

 attach(observer) {
 this.observers.push(observer); //adding new observer
 }

 detach(observer) {
 this.observers = this.observers.filter(obs => obs !== observer); 
 //removing an observer in case of unsubscribing from notification service
 }

 notify(data) {
 this.observers.forEach(observer => observer.update(data));
 }
}

class Product extends Observable {
 constructor(name, price) {
 super();
 this._name = name;
 this._price = price;
 }

// calling notify() whenever product value changes
 set name(newName) {
 this._name = newName;
 this.notify(`Product name updated to: ${newName}`);
 }

 set price(newPrice) {
 this._price = newPrice;
 this.notify(`Price updated to: $${newPrice}`);
 }
}


// creating an observer class to identify each observer
class Observer {
 constructor(name) {
 this.name = name;
 }

 update(message) {
 console.log(`${this.name} received update: ${message}`);
 }
}

// Usage Example:
const product = new Product("Laptop", 1000);

const observer1 = new Observer("Observer 1");
const observer2 = new Observer("Observer 2");

product.attach(observer1);
product.attach(observer2);

product.price = 1200; // Notifies observers
product.name = "Gaming Laptop"; // Notifies observers

observable.notify("New Event Occurred!"); // Both observers get notified

const product = new Product("Laptop", 1000);

const observer1 = new Observer("Observer 1");
const observer2 = new Observer("Observer 2");

product.attach(observer1);
product.attach(observer2);

product.price = 1200; // Notifies observers
product.name = "Gaming Laptop"; // Notifies observers

observable.notify("New Event Occurred!"); // Both observers get notified
Enter fullscreen mode Exit fullscreen mode

๐ŸŒŸ Key Takeaways
โœ… Loose Coupling: The observable and observers interact with minimal dependency.
โœ… Flexibility: New observers can be added/removed dynamically.
โœ… Real-World Use Cases: Notification services, stock market updates, event-driven systems.
Whatโ€™s your take on the Observer Pattern? Have you encountered it in real-world scenarios? Letโ€™s discuss in the comments! ๐Ÿš€

Top comments (0)