Learning Design Patterns - Observer Pattern

This week I’ll be subscribing to the Observer Pattern in my series on design patterns plucked from this book and from examples on the Internet.

What is it?
The Observer Pattern helps keep your objects in the know; i.e., communicating with other objects about important events.

The pattern is analogous to a newspaper company and its subscribers. Say one day your power gets turned off by the electric utility since you haven’t paid your bill for six months (this actually happened to me one time; it was the first apartment my wife and I lived in and I assumed that the power would be transferred over to me and I’d get a bill. Evidently I needed to call the utility and subscribe, and since I didn’t, they figured I was Freddy the Freeloader and cut off my juice). When your power is cut off, you realize pretty quickly how dependant you are on it for everything from your electric can opener to your TV, and especially to the Internet. So, jonesing for some news, you call up the newspaper company and subscribe to the paper (it will be at least another 6 months before they realize you can’t pay, and by that time you should have your electricity back anyway). The newspaper company adds you to their list of subscribers, and lo-and-behold the next morning you’re awaken to the thunderous bang of a paper propelled into your front door by a kid with major-league hopes. In fact, every time the newspaper publishes a paper, they make sure you get one as long as your on their list. And when you cancel your account, or they revoke your subscriptions for lack of funds, they’ll take you off their list of subscribers and you’ll stop getting the paper when they publish it.

That’s pretty much it. There’s a publisher, sometimes called the "Subject" and subscribers, also called "Observers". There are a few different ways to implement the pattern, though, like whether the publisher just notifies subscribers of changes, or whether it allows subscribers to get part or all of the data by themselves, or some of both.

Where is it used?
To maintain state and notify other objects of changes. Some examples include a stock-ticker application, weather data service, and machine health and status (e.g., CPU temp, fan speed, etc.).

But why?
Letting the publisher control the data in one place, and then notify any interested subscriber objects when that data changes, is cleaner than controlling the data in each potential subscriber object and separately updating each when that data changes.

The relationship between the publisher and subscriber is described as "loose coupling" because they do interact, but they aren’t so dependant on one another that changing one will affect the other. All that matters to the publisher is that the subscriber implements an observer interface, and all that matters to the subscriber is that the publisher implements a subject interface. The loosely coupled relationship minimizes dependencies, and promotes a flexible design.

OK, and how is it implemented?
The publisher and subscriber each need to implement an interface; to notify and update, respectively.

// Publisher interface
public interface IPublisher {
	public void registerSubscriber(ISubscriber subscriber);
	public void removeSubscriber(ISubscriber subscriber);
	public void notifySubscribers();
}

// Subscriber interface
public interface ISubscriber {
	public void update();
}

//Publisher
public class JournalStarNews implements IPublisher {
	private ArrayList subscribers;
	private string news;

	public JournalStarNews() {
		subscribers = new ArrayList();
	}

	public void registerSubscriber(ISubscriber subscriber) {
		subscribers.add(subscriber);
	}

	public void removeSubscriber(ISubscriber subscriber) {
		int i = subscribers.indexof(subscriber);
		if (i >= 0) {
			subscribers.remove(i);
		}

	public void notifySubscribers() {
		for (int i = 0; i < subscribers.size(); i++) {
			ISubscriber subscriber = (ISubscriber)subscribers.get(i);
			subscriber.update();
		}

	public void hotOffThePress(string News) {
		news = News;
		notifySubscribers();
		}

	public string getNews() {
		return news;
		}

}

//Subscriber
public class NewspaperReader implements ISubscriber {
	private string news;
	private IPublisher JournalStarNews;

	public NewspaperReader(IPublisher JournalStarNews) {
		this.JournalStarNews = JournalStarNews;
		JournalStarNews.registerSubscriber(this);
	}

	public void update() {
		this.news = JournalStarNews.getNews();
	}
}

Further Reading