Behavioral Design Pattern · Java

Observer Design Pattern in Java

Notify interested objects automatically when a subject changes its state.

What is Observer?

The Observer pattern creates a one-to-many relationship between objects. When the Subject changes, it notifies all registered Observers automatically. This keeps the stock market independent from its investors: the stock market only sends updates, while each investor decides what to do with the new price. This loose coupling makes reactive and event-driven systems easier to extend.

Beginner-friendly Java example

Focus on the roles in the example first. The pattern becomes easier when you can identify the sender, receiver, context, state, or strategy involved.

// Step 1: Define the Subject interface
interface Subject {
    void registerObserver(Observer observer);
    void removeObserver(Observer observer);
    void notifyObservers();
}

// Step 2: Implement the Subject
import java.util.ArrayList;
import java.util.List;

class StockMarket implements Subject {
    private List<Observer> observers = new ArrayList<>();
    private String stockName;
    private double price;

    public void setStockData(String stockName, double price) {
        this.stockName = stockName;
        this.price = price;
        notifyObservers();
    }

    @Override
    public void registerObserver(Observer observer) {
        observers.add(observer);
    }

    @Override
    public void removeObserver(Observer observer) {
        observers.remove(observer);
    }

    @Override
    public void notifyObservers() {
        for (Observer observer : observers) {
            observer.update(stockName, price);
        }
    }
}

// Step 3: Define the Observer interface
interface Observer {
    void update(String stockName, double price);
}

// Step 4: Implement the Observer
class Investor implements Observer {
    private String name;

    public Investor(String name) {
        this.name = name;
    }

    @Override
    public void update(String stockName, double price) {
        System.out.println(name + " received update: "
            + stockName + " price is now $" + price);
    }
}

// Step 5: Test the implementation
public class Main {
    public static void main(String[] args) {
        StockMarket stockMarket = new StockMarket();

        Investor investor1 = new Investor("John");
        Investor investor2 = new Investor("Alice");

        // Register investors for stock updates
        stockMarket.registerObserver(investor1);
        stockMarket.registerObserver(investor2);

        // A price change automatically notifies all investors
        stockMarket.setStockData("ABC", 100.0);
    }
}

Benefits and trade-offs

Benefits
  • Keeps responsibilities focused.
  • Reduces conditional and tightly coupled code.
  • Makes behavior easier to extend and test.
Trade-offs
  • Can introduce extra objects and interfaces.
  • Too many small classes can make simple logic harder to follow.

Real-time use cases

  • Stock market price notifications
  • Email and SMS alerts
  • Domain events and messaging
  • UI state updates
  • Weather monitoring systems
Key takeawayNotify interested objects automatically when a subject changes its state. Use it when behavior or communication is changing faster than the objects themselves.