In this tutorial, we’ll talk about the Observer design pattern.
There are two main aspects to the observer pattern – a Subject and the Observers. We use this pattern when our system has multiple objects, known as the observers, relying on the state of one particular object – the subject. All the observers register themselves to the subject. Whenever there is a change in subject’s state, all these observers get notified.
One real-world example of the usage of this observer pattern is the blog subscription. If you subscribe to the blog you like, you receive notifications as soon as it has any updates.
With this, let’s deep-dive on the concepts.
We can represent the observer design pattern with the following UML:
Where we have:
Let’s say we want to notify our blog subscribers as soon as we publish a new post. Let’s implement it using the observer pattern.
To do so, we first define our Subject class:
public abstract class Subject { private List<Observer> observers = new ArrayList<>(); public void register(Observer observer) { this.observers.add(observer); } public void unregister(Observer observer) { if(this.observers.contains(observer)) { this.observers.remove(observer); } } public void notifyAll() { for(Observer o : observers) { o.update(); } } }
The reason we have marked the Subject class as abstract is that we want a Subject to have at least some state.
Now that we have implemented our Subject superclass, let’s write our Blog class:
public class Blog extends Subject { private String title; private String author; public Blog(String title, String author) { this.title = title; this.author = author; } public void publish(Post post) { //code to publish a new post ... notifyAll(); } public Post getRecentPost() { ... } ... }
Our Blog class extends from Subject and invokes notifyAll() method within the post() method to notify all subscribers as soon as an article gets published.
Let’s now define our Observer interface and the Subscriber class:
public interface Observer { void update(); } public class Subscriber implements Observer { private String name; private Subject subject; public Subscriber(String name) { this.name = name; } public void subscribeTo(Subject subject) { subject.register(this); this.subject = subject; } public void unsubscribeFrom(Subject subject) { subject.unregister(this); this.subject = null; } @Override public void update() { if(this.subject == null) { System.out.println("Not yet subscribed!"); return; } //get the last published post Post recentPost = this.subject.getRecentPost(); System.out.println(this.name + ", a new post got published: " + recentPost); } }
Note that a blog subscriber will use the subscribeTo() method to subscribe to a blog. Once the user is subscribed to a blog, he/she will automatically receive an update of any new posts published.
Let’s quickly test out our code:
//in the main method Subject programmerGirlBlog = new Blog("ProgrammerGirl", "Shubhra"); Observer james = new Subscriber("James"); Observer selena = new Subscriber("Selena"); james.subscribeTo(programmerGirlBlog); selena.subscribeTo(programmerGirlBlog); Post compositeDesignPattern = new Post("Composite Design Pattern"); programmerGirlBlog.publish(compositeDesignPattern);
On executing the above code, we’ll have an output somewhat like:
James, a new post got published: Composite Design Pattern ... Selena, a new post got published: Composite Design Pattern ...
In this quick tutorial, we learned to implement the Observer design pattern. This design pattern is used to implement the publisher-subscriber JMS model. Also, classes like java.util.EventListener and javax.servlet.http.HttpSessionAttributeListener makes use of this pattern.
Moreover, it is good to know that Java provides basic implementations of the observer and the subject classes named as java.util.Observer and java.util.Observable respectively.