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

🌟 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! 🚀