The blog for Design Patterns, Linux, HA and Myself!
In this tutorial we’ll be looking into Observer Design Pattern. We will learn about the Observer Design Pattern by creating a subscription system for a Magazine Company. There will be some design problems that we’ll find, and then we’ll apply the Observer Design Pattern to solve those problems.
This magazine company, ReadDigest, has a complex algorithm of creating the weekly article. It wants to send the newly generated articles to it’s subscribers but it doesn’t know how to do it.
This is the problem that we’ve to solve.
It has provided us the API that is called whenever new content is generated.
Note: Make sure to go through the code comments as well. It’ll help you understand the concept better.
abstract class ReadDigest {
// The title of the current edition
private String currentTitle;
// Some information about the current edition
private String moreInfo;
// This method is called whenever there is some new content available
abstract void onNewContent();
// This method generates the new content for the magazine
// and calls onNewContent() for broadcasting the info.
void generateContent() {
// some complex technique to create content and it's code is hidden from the mere mortals
:
:
:
// finally, call the onNewContent() method
this.onNewContent();
}
}
Currently, it has 3 subscribers, a Race car Driver
, a Newspaper Man
and a Movie Director
.
The class for the Race car driver:
class RaceCarDriver {
void receiveNewContent(String title, String moreContent) {
System.out.println("RaceCarDriver Receives...");
System.out.println(title);
System.out.println(moreContent);
}
}
The class for the Newspaper man:
class NewsPaperMan {
void receiveNewArticle(String title, String moreContent) {
System.out.println("NewsPaperMan Receives...");
System.out.println(title);
System.out.println(moreContent);
}
}
And, the class for the Movie director:
class MovieDirector {
void receiveNewMediaStory(String title, String moreContent) {
System.out.println("MovieDirector Receives...");
System.out.println(title);
System.out.println(moreContent);
}
}
If you read the classes of the subscribers of the Magazine company then you’ll find that each of them have a method to get the latest information from the Read Digest magazine company. So, in our solution all we have to do is to call these methods of the subscribers whenever new content is generated.
The first solution that comes into our mind is to just hook our subscription algorithm into it, i.e., to notify the
subscribers one by one whenever new content is published. The method, onNewContent()
, looks like the best place to add
that code.
class ReadDigestWithSubscription extends ReadDigest {
private RaceCarDriver raceCarDriver;
private NewsPaperMan newsPaperMan;
private MovieDirector movieDirector;
ReadDigestWithSubscription(RaceCarDriver raceCarDriver, NewsPaperMan newsPaperMan, MovieDirector movieDirector) {
this.movieDirector = movieDirector;
this.raceCarDriver = raceCarDriver;
this.newsPaperMan = newsPaperMan;
}
void onNewContent() {
raceCarDriver.receiveNewContent(this.getCurrentTitle(), this.getMoreInfo());
newsPaperMan.receiveNewArticle(this.getCurrentTitle(), this.getMoreInfo());
movieDirector.receiveNewMediaStory(this.getCurrentTitle(), this.getMoreInfo());
}
}
And, we are able to successfully notify all the customers of ReadDigest whenever there’s some new info available and because of this more and more customers want to become the subscribers of the magazine.
So, how to add more subscribers? By adding more objects inside the ReadDigestWithSubscription
class? By adding more
arguments in the constructor of the ReadDigestWithSubscription
? By adding one new line for one new subscriber into the
method onNewContent()
?
While we’re able to solve the problem but there are a few mistakes that we cannot ignore. Let’s look at them:
Now that we know the mistakes. Let’s try to fix them by using Observer Design Pattern.
In observable design pattern there are two types of classes:
The Observable keeps a list of Observers and notifies them whenever the it’s state changes.
Looks like it is a right fit for us!
The Read Digest Magazine CompanyObservable keeps a list of SubscribersObservers and notifies them whenever the it’s contentstate changes.
The Read Digest company becomes the Observable and the Subscribers become the Observers. We’ll be using Java’s own Observer classes. But you can create your own if you want.
The ReadDigest class will now extend java.util.Observable
and it will inherit following three methods that we’ll
require:
addObservers(Observer o)
used for adding a observer. This will add them in a List of Observers(List<Observer>)
inside the Observable
or the Read Digest Magazine company.setChanged()
used for marking the status of the Read Digest Magazine Company changed.notifyObservers()
used for notifying the observers whenever the state is changed.class ReadDigest extends java.util.Observable {
private String currentTitle;
private String moreInfo;
void generateContent() {
// some complex technique to create content and it's code is hidden from the mere mortals
:
:
:
// finally, set the status of the Read Digest Changed
// and call the notifyObservers
this.setChanged();
this.notifyObservers();
}
}
The classes RaceCarDriver
, NewsPaperMan
, and MovieDirector
will now extend java.util.Observer
and it will inherit
following one methods that we’ll require:
update(Observable o, Object arg)
this method will be called by the Observable or Read Digest Magazine Company
whenever it call the notifyObservers
The new version of RaceCarDriver
class RaceCarDriver implements java.util.Observer {
private void receiveNewContent(String title, String moreContent) {
System.out.println("RaceCarDriver Receives...");
System.out.println(title);
System.out.println(moreContent);
}
@Override
public void update(Observable o, Object arg) {
if (o instanceof ReadDigest) {
ReadDigest readDigest = (ReadDigest) o;
this.receiveNewContent(readDigest.getCurrentTitle(), readDigest.getMoreInfo());
}
}
}
Using this new implementation we’ve made sure that the Race Car Driver(or the Observers) and the Magazine Company( or the observables are loosely coupled). All they about them is that they are either an Observer or an Observable, nothing more than that.
And because all the observers are of same type now, it will be easy to add/update or delete them.
This the UML class diagram:
Finally the definition from the Wikipedia
The observer pattern is a software design pattern in which an object, called the subject, maintains a list of its dependents, called observers, and notifies them automatically of any state changes, usually by calling one of their methods.
I’ve created these tutorials after learning Design Patterns from this book Head First Design Patterns (A Brain Friendly Guide).