Software Development Engineer

Blog PostsResume

Object Oriented Design - Observer Pattern

The Observer Design Pattern is a behavioral design pattern that defines a one-to-many dependency between objects so that when one object changes state, all its dependents are notified and updated automatically. The object that is watched is called the subject, and the objects that are watching the state changes are called observers.

How it works?

  • The subject contains a method to attach observers that wish to be notified of changes - subscribe()
  • The subject also contains a method to remove observers - unsubscribe()
  • When a change occurs in the subject, it broadcasts a notification to all registered observers - notify()
  • Observers use the notification to perform their ow logic that should occur when the subject changes.

Design a System that Notifies Users when an Out-of-Stock product is back in Stock

Designing a Low-Level Design (LLD) for a system that notifies users when an out-of-stock product is back in stock using the Observer Pattern involves several steps. The Observer Pattern is ideal for this situation as it allows users (observers) to be notified of changes in the available stock of a product (subject).

1. Product Class (Subject)

The Product class represents the subject. It maintains a list of observers (User) and notifies them when the stock status changes.

interface Product {
	void subscribe(User user);
	void unsubscribe(User user);
	void notify();
	void setStockCount(int count);
}

public class Playstaion implements Product {
	private String productId;
	private int stockCount;
	private Set<User> observers;

	public Playstation(final String productId) {
		this.productId = productId;
		this.stockCount = 0;
		this.observers = new HashSet<>();
	}

	public void subscribe(final User user) {
		this.observers.add(user);
	}

	public void unsubscribe(final User user) {
		this.observers.remove(user);
	}

	public void notify() {
		for (User user : this.observers) {
			user.update(this);
		}
	}

	public void setStockCont(final int count) {
		if (count == 0) {
			notify();
			return;
		}

		this.stockCount += count;
	}
}

2. User class (Observer)

The User class represents the observer. It defines the update method, which is called when the Product they are observing changes its state (back in stock).

interface ProductObserver {
	void update(Product product);
}

public class User implements ProductObserver {
	// ... other member attributes and methods ...

    @Override
    public void update(Product product) {
		System.out.println("Notifying " + name + " via email " + email +
                               ": Product " + product.getProductId() + " is back in stock!");
        // Here, you'd integrate with an actual email service to send the notification
    }
}

How does Observer Pattern follow SOLID Principles?

The Observer pattern aligns well with the SOLID principles, which are guidelines for designing maintainable and extendable object-oriented software. Let's examine how the Observer pattern adheres to each of the SOLID principles:

1. Single Responsibility Principle (SRP)

  • The subject has the sole responsibility of managing its internal state and notifying observers about any changes. It does not concern itself with how observers handle the notifications.
  • The observers are responsible only for responding to notifications they receive.

2. Open/Closed Principle (OCP)

  • The Observer Pattern is open for extension but closed for modification. You can add new observer types without altering the subject's code.
  • New types of observers (like Admin, Vendor, etc.) can be added without changing existing code (Product or User). The system is extendable for new functionalities.

3. Liskov Substitution Principle (LSP)

  • In the Observer Pattern, the LSP emphasizes that subclasses of the Observer interface should be able to replace each other without affecting the functionality of the Subject.
  • From the Subject's point of view, it doesn't matter what specific type of Observer is attached to it. The Subject uses the Observer interface to communicate with its observers. Whether the actual observer is a User or an Admin is irrelevant to the Subject's functioning; it only cares that each observer adheres to the Observer interface contract.

4. Interface Segregation Principle (ISP)

  • The subject might implement an interface with methods for subscribing, unsubscribing, and notifying observers.
  • Observers implement an interface (or abstract class) with a single notify method. This ensures that observers are not forced to depend on methods they do not use.

5. Dependency Inversion Principle (DIP)

  • In the Observer Pattern, high-level modules (subject) are not dependent on low-level modules (individual observers). Instead, both depend on abstractions.
  • Observers do not need to know the internal workings of the subject; they only rely on its interface.
  • Both high-level (Product) and low-level (User) modules depend on abstractions (Observer, Subject). Product does not depend on the specifics of User, only on the Observer interface.

Design Examples for Observer Pattern

1. Library Management System

  • Use Case: Notify subscribers when a book becomes available, or inform staff when books are due for return.
  • Application: Books or inventory management can be subjects, while subscribers or staff are observers.

2. Parking Lot System

  • Use Case: Notify the entry and exit gates or display boards when parking spots are occupied or become available.
  • Application: Parking spots are subjects, and gates or display boards are observers.

3. Movie Ticket Booking System

  • Use Case: Notify users when new movies are added, showtimes are available, or when there are changes in bookings.
  • Application: The movie schedule system is the subject, and registered users are observers.

4. Ride Sharing Service like Uber or Lyft

  • Use Case: Notify drivers when a new ride request is made or update customers about driver location.
  • Application: The ride request system is the subject, and drivers and customers are observers.

5. Vending Machine

  • Use Case: Notify maintenance when stock is low.
  • Application: The stock monitoring system is the subject, and maintenance personnel are observers.

6. Social Media Platform like Twitter

  • Use Case: Notify users when people they follow post new content or when they receive likes or comments.
  • Application: User accounts are subjects, and follower feeds or notification systems are observers.

7. Dashboard Displaying All Running Flights Over World Map

  • Use Case: Update the dashboard when flight statuses change.
  • Application: Each flight is a subject, and the dashboard is an observer.

8. Ticket Resolution System for Big Ecommerce Company

  • Use Case: Update customer service agents when new tickets are created or when there are updates.
  • Application: The ticketing system is the subject, and customer service agents are observers.

9. Amazon Prime Video

  • Use Case: Notify users about new releases, recommended shows, or changes in subscription status.
  • Application: The content management system is the subject, and users are observers.

© 2024 Ujjwal Bhardwaj. All Rights Reserved.