Observer Design Pattern In Java
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.
UML Representation:
We can represent the observer design pattern with the following UML:
Where we have:
- the Subject: maintains a list of observers, provides methods to register/unregister observers. Also, has a notifyAll() method to notify all registered observers of any state change
- SubjectImpl: the class extending the functionality of the Subject class, it holds a state object representing its current state. Note that it’s a good idea to have an immutable state object to prevent any unintentional updates by the observer
- Observer: it’s an interface with an update() method which is invoked by the Subject to notify the observer of any changes in its current state
- ConcreteObserver: these are the classes implementing the Observer interface, the observer objects register themselves to listen to a Subject
Blog Subscription Example:
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:
01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16 17 18 19 20 | 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:
01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16 17 18 19 20 | 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.
Implementing Observer:
Let’s now define our Observer interface and the Subscriber class:
01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 | 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.
Testing Our Implementation:
Let’s quickly test out our code:
01 02 03 04 05 06 07 08 09 10 11 12 | //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:
1 2 | James, a new post got published: Composite Design Pattern ... Selena, a new post got published: Composite Design Pattern ... |
Conclusion:
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.
Published on Java Code Geeks with permission by Shubhra Srivastava, partner at our JCG program. See the original article here: Observer Design Pattern In Java Opinions expressed by Java Code Geeks contributors are their own. |