When one object changes, multiple dependent objects need to be notified. You don't want the subject to know about every observer. Observer decouples the subject (publisher) from observers (subscribers).
// ─── EXAMPLE 1 ──────────────────────────────────────────────────────────────
// WHAT WE ARE IMPLEMENTING:
// An online store inventory monitor alerting waiting buyers immediately when
// an out-of-stock item is replenished.
//
// WHERE THE OBSERVER FITS IN:
// Subject is the Observable (e.g., Product). Observer is the Subscriber
// interface. Customer classes act as Concrete Observers.
// ────────────────────────────────────────────────────────────────────────────
import java.util.concurrent.CopyOnWriteArrayList;
// --- Observer interface ---
interface StockObserver {
void update(String symbol, double price);
}
// --- Subject ---
class StockMarket {
private final java.util.List<StockObserver> observers = new CopyOnWriteArrayList<>();
private final java.util.Map<String, Double> prices = new java.util.HashMap<>();
public void addObserver(StockObserver obs) { observers.add(obs); }
public void removeObserver(StockObserver obs) { observers.remove(obs); }
public void setPrice(String symbol, double price) {
prices.put(symbol, price);
notifyObservers(symbol, price);
}
private void notifyObservers(String symbol, double price) {
for (StockObserver obs : observers) {
obs.update(symbol, price);
}
}
}
// --- Concrete observers ---
class MobileApp implements StockObserver {
private final String name;
public MobileApp(String name) { this.name = name; }
public void update(String symbol, double price) {
System.out.println(" [MobileApp " + name + "] " + symbol + " now $" + price);
}
}
class EmailAlertService implements StockObserver {
public void update(String symbol, double price) {
if (price > 500) {
System.out.println(" [EMAIL ALERT] " + symbol + " crossed $500 at $" + price);
}
}
}
class TradingBot implements StockObserver {
public void update(String symbol, double price) {
if (price < 50) {
System.out.println(" [TradingBot] Buying " + symbol + " at $" + price);
}
}
}
public class Main {
public static void main(String[] args) {
StockMarket market = new StockMarket();
market.addObserver(new MobileApp("Alice"));
market.addObserver(new MobileApp("Bob"));
market.addObserver(new EmailAlertService());
market.addObserver(new TradingBot());
System.out.println("--- Price Update: AAPL ---");
market.setPrice("AAPL", 150.0);
System.out.println("\n--- Price Update: TSLA ---");
market.setPrice("TSLA", 520.0);
}
}