Observer Pattern
Observable
Software Design
Programming
Design Patterns

When should we use Observer and Observable?

Object-Oriented Design practice on Codemia

Turn requirements into classes, and defend the design, on the problems that come up in OOD rounds.

Practice OOD

Overview of Observer and Observable

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. In many programming languages, this pattern helps build scalable and modular systems by decoupling the components that generate data (Subjects/Observables) from the components that consume them (Observers).

This pattern is particularly useful in areas where changes to one part of the system need to be broadcasted to the rest of the system without tight coupling. It is often used in modern frameworks for developing reactive applications, such as RxJava for reactive Java programming.

Key Components

  • Observable: The object being observed. It holds the state, and when a change occurs, it notifies its observers.
  • Observer: The object that gets notified when the observable changes.

Detailed Explanation

When to Use Observer and Observable

Using Observables and Observers is beneficial in the following situations:

  1. Decoupling Components: When you need to decouple a component generating data or changes from the components that act upon these changes. This allows for cleaner architecture.
  2. Event Handling: In scenarios where events need to trigger various parts of a system, Observers can register themselves to listen for changes.
  3. Reactive Programming: In frameworks like RxJS, Observables are used to provide a clean API for asynchronous programming and event-based architectures.
  4. Dynamic Behavior: When the number of consumers of the data or events is unknown at compile time, and their behavior might change at runtime.

Technical Explanation

Let's explore an example using Java to demonstrate how Observable and Observer work together:

java
1import java.util.Observable;
2import java.util.Observer;
3
4// Create a Stock Observable that extends the Observable class
5class Stock extends Observable {
6    private String stockName;
7    private double stockPrice;
8
9    public Stock(String stockName, double stockPrice) {
10        this.stockName = stockName;
11        this.stockPrice = stockPrice;
12    }
13
14    public void setStockPrice(double newPrice) {
15        this.stockPrice = newPrice;
16        setChanged(); // Mark the observable as changed
17        notifyObservers(); // Notify all observers
18    }
19
20    public double getStockPrice() {
21        return stockPrice;
22    }
23}
24
25// Create a StockObserver class that implements the Observer interface
26class StockObserver implements Observer {
27    private String observerName;
28
29    public StockObserver(String observerName) {
30        this.observerName = observerName;
31    }
32
33    @Override
34    public void update(Observable observable, Object arg) {
35        if (observable instanceof Stock) {
36            Stock stock = (Stock) observable;
37            System.out.println(observerName + " notified. New stock price: " + stock.getStockPrice());
38        }
39    }
40}
41
42public class ObserverExample {
43    public static void main(String[] args) {
44        Stock googleStock = new Stock("Google", 1234.56);
45
46        StockObserver observer1 = new StockObserver("Observer 1");
47        StockObserver observer2 = new StockObserver("Observer 2");
48
49        googleStock.addObserver(observer1);
50        googleStock.addObserver(observer2);
51
52        googleStock.setStockPrice(1250.00);
53    }
54}

Key Observations

  • Observable Class: The Stock class is the source of data and changes. It uses methods setChanged() and notifyObservers() to update its state and inform Observers of changes.
  • Observer Interface: Each observer implements the Observer interface and defines the update() method to react to changes from the Observable.
  • Add/Remove Observers: The addObserver() method is used to register observers. Observers can also be removed using deleteObserver().

Summary Table

Below is a table summarizing when and why to use Observer and Observable:

Use ScenarioKey Considerations
DecouplingUseful for separating state change notifications from logic.
Event HandlingEfficient structure for managing events and updates.
Reactive ProgrammingSupports event-driven and asynchronous programming paradigms.
Dynamic BehaviorAllows for changing observer behavior or count at runtime.
UI Component UpdatesIdeal for GUI applications where components re-render on state changes.

Additional Considerations

1. Thread Safety

When using Observables in multi-threaded environments, ensure that state changes and observer notifications are done in a thread-safe manner to prevent race conditions and inconsistent state reporting.

2. Memory Leaks

Ensure observers can be dereferenced and removed appropriately to prevent memory leaks, especially in long-running applications.

3. Performance

Excessive use of observers can lead to performance bottlenecks if there are too many notifications or complex state updates, so it's advisable to manage the rate and number of updates.

4. Alternatives

Consider alternative patterns such as the Publish-Subscribe if your use case involves broadcast-like communication more suited for a message queue model as opposed to a direct notification model.

Understanding the advantages and drawbacks of using Observers and Observables can aid in making well-informed decisions while architecting software systems. This pattern can improve maintainability and scalability when properly implemented in appropriate scenarios.


Related reading
Course
Intermediate
27 lessons
14 hours
OOD Fundamentals

Master object-oriented design from first principles, SOLID, design patterns, and classic interview problems with hands-on coding.

View the course
Track what you have practised

A free account saves your progress, solutions and study plan across every problem on Codemia.

Object-Oriented Design practice on Codemia

Turn requirements into classes, and defend the design, on the problems that come up in OOD rounds.

Practice OOD

All Rights Reserved.