The Observer Pattern
Category: Behavioral
The Observer pattern defines a one-to-many dependency between objects so that when one object changes state, all its dependents are notified and updated automatically.
This pattern is also heavily known as the Publish-Subscribe (Pub/Sub) pattern. It is widely used in event-driven programming, GUI frameworks (like clicking a button), and real-time data streaming applications.
Example: The News Agency
Imagine a NewsAgency (the Publisher/Subject). When breaking news happens, it needs to instantly notify various NewsChannels (the Subscribers/Observers) so they can broadcast it.
Instead of the News Channels constantly checking the News Agency to ask "Is there new news?" (Polling), the Observer pattern flips it: the News Channels subscribe to the News Agency, and the Agency pushes the news to them only when it happens.
1. The Subject (Publisher) Interface
The Subject must have methods to attach, detach, and notify observers.
public interface Subject {
void attach(Observer o);
void detach(Observer o);
void notifyObservers();
}
2. The Observer (Subscriber) Interface
The Observer must have an update() method that the Subject can call.
public interface Observer {
void update(String news);
}
3. The Concrete Subject
This is the News Agency. It maintains a list of all active subscribers. When its internal state changes (news breaks), it loops through the list and notifies everyone.
import java.util.ArrayList;
import java.util.List;
public class NewsAgency implements Subject {
// The list of subscribers
private List<Observer> channels = new ArrayList<>();
// The internal state
private String breakingNews;
public void setBreakingNews(String news) {
this.breakingNews = news;
notifyObservers(); // Trigger notifications immediately!
}
@Override
public void attach(Observer o) {
channels.add(o);
}
@Override
public void detach(Observer o) {
channels.remove(o);
}
@Override
public void notifyObservers() {
for (Observer channel : channels) {
// Pushing the news to the subscriber
channel.update(this.breakingNews);
}
}
}
4. Concrete Observers
These are the individual news channels.
public class NewsChannel implements Observer {
private String channelName;
public NewsChannel(String name) {
this.channelName = name;
}
@Override
public void update(String news) {
System.out.println(channelName + " Breaking News Broadcast: " + news);
}
}
5. Client Code
public class LabObserver1 {
public static void main(String[] args) {
// 1. Create the Publisher
NewsAgency reuters = new NewsAgency();
// 2. Create the Subscribers
NewsChannel cnn = new NewsChannel("CNN");
NewsChannel bbc = new NewsChannel("BBC");
// 3. Subscribe the channels to the agency
reuters.attach(cnn);
reuters.attach(bbc);
// 4. Trigger an event!
System.out.println("--- Reuters sets breaking news ---");
reuters.setBreakingNews("Observer Pattern Discovered!");
// Output:
// --- Reuters sets breaking news ---
// CNN Breaking News Broadcast: Observer Pattern Discovered!
// BBC Breaking News Broadcast: Observer Pattern Discovered!
}
}