Observer Design Pattern
Observer Design Pattern is one of the Behavioral Design Pattern. Observer design pattern is useful when you are interested in the state of an object and want to get notified whenever there is any change.
Definition
GoF Definition : The Observer Design Pattern defines a one-to-many dependency between objects so that when one object changes state, all of its dependents are notified and updated automatically.
The object which is being watched is called the subject. The objects which are watching the state changes are called observers or listeners.
Concept
In this pattern, there are many observers (objects) which are observing a particular subject (object). Observers are basically interested and want to be notified when there is a change made inside that subject. So, they register themselves to that subject. When they lose interest in the subject they simply unregister from the subject. Sometimes this model is also referred to as the Publisher-Subscriber model.
Real-Life Example
Twitter Follow button: We can think about a celebrity who has many followers on twitter. Each of these followers wants to get all the latest updates of his/her favorite celebrity. So, he/she can follow the celebrity as long as his/her interest persists. When he loses interest, he simply stops following that celebrity. Here we can think of the follower as an observer and the celebrity as a subject.
Java Implementation
Let's Implement above Twitter Follow Button example using Java.
Java provides in-built platform for implementing Observer pattern through java.util.Observable
class and java.util.Observer
interface.
However it’s not widely used because the implementation is really simple and most of the times we don’t want to end up extending a class just for implementing Observer pattern as java doesn't provide multiple inheritance in classes.
I prefer having my own Subject and Observer interface and here is my java code implementation of Observer Design Pattern.
import java.util.ArrayList; /** * This interface handles adding, deleting and updating all observers */ interface Subject{ public void register(Observer o); public void unregister(Observer o); public void notifyAllObservers(String s); } /** * The Observers update method is called when the Subject changes */ interface Observer{ public void update(String name, String s); } /** * This class extends Subject interface. */ class Celebrity implements Subject{ private String celebrityName; //name of the celebrity private ArrayList<Observer> followers; //list of followers public Celebrity(String celebrityName) { this.celebrityName = celebrityName; followers = new ArrayList<Observer>(); } /** * add follower to the celebrity's registered follower list */ @Override public void register(Observer o) { followers.add(o); System.out.println(o + " has started following " + celebrityName); } /** * remove follower from celebrity's registered follower list */ @Override public void unregister(Observer o) { followers.remove(o); System.out.println(o + " has stopped following " + celebrityName); } /** * Notify all the registered followers */ @Override public void notifyAllObservers(String tweet) { for(Observer follower : followers) { follower.update(celebrityName, tweet); } System.out.println(); } /** * This method updates the tweet. * It will internally call notifyAllObservers(tweet) method * after updating the tweet. * */ public void tweet(String tweet) { System.out.println("\n" + celebrityName + " has tweeted :: " + tweet + "\n"); notifyAllObservers(tweet); } } /** * This class extends Observer interface. */ class Follower implements Observer{ private String followerName; public Follower(String followerName) { this.followerName = followerName; } /** * This method will be called to update all followers regarding the * new tweet posted by celebrity. */ @Override public void update(String celebrityName , String tweet) { System.out.println(followerName + " has received "+ celebrityName + "'s tweet :: "+ tweet); } @Override public String toString() { return followerName; } } public class ObserverDesignPattern { public static void main(String[] args) { Celebrity amirkhan = new Celebrity("Amirkhan"); Celebrity selenaGomez = new Celebrity("Selena Gomez"); Follower amar = new Follower("Amar"); Follower juhi = new Follower("Juhi"); Follower urja = new Follower("Urja"); Follower malay = new Follower("Malay"); Follower ankit = new Follower("Ankit"); Follower harsh = new Follower("Harsh"); amirkhan.register(amar); amirkhan.register(juhi); amirkhan.register(urja); selenaGomez.register(malay); selenaGomez.register(ankit); selenaGomez.register(harsh); amirkhan.tweet("Hey guys, came across this interesting trailer, check it out."); selenaGomez.tweet("Good Morning..!!"); amirkhan.unregister(juhi); amirkhan.tweet("Teaser of Secret Superstar has been released..!!"); } }
Download Complete Java Program »
output:
Amar has started following Amirkhan Juhi has started following Amirkhan Urja has started following Amirkhan Malay has started following Selena Gomez Ankit has started following Selena Gomez Harsh has started following Selena Gomez Amirkhan has tweeted :: Hey guys, came across this interesting trailer, check it out. Amar has received Amirkhan's tweet :: Hey guys, came across this interesting trailer, check it out. Juhi has received Amirkhan's tweet :: Hey guys, came across this interesting trailer, check it out. Urja has received Amirkhan's tweet :: Hey guys, came across this interesting trailer, check it out. Selena Gomez has tweeted :: Good Morning..!! Malay has received Selena Gomez's tweet :: Good Morning..!! Ankit has received Selena Gomez's tweet :: Good Morning..!! Harsh has received Selena Gomez's tweet :: Good Morning..!! Juhi has stopped following Amirkhan Amirkhan has tweeted :: Teaser of Secret Superstar has been released..!! Amar has received Amirkhan's tweet :: Teaser of Secret Superstar has been released..!! Urja has received Amirkhan's tweet :: Teaser of Secret Superstar has been released..!!
The most popular use of Observer pattern is in Model View Controller (MVC) architectural pattern.
Memory leaks
Main issue with Observer pattern is that it can cause memory leaks. The subject holds a strong reference to observers. If observers are not de-registered in time, it can lead to memory leak.
Existing Implementation in JDK and J2EE
-
java.util.Observer
/java.util.Observable
(rarely used in real world though) -
All implementations of
java.util.EventListener
(practically all over Swing) . In Swing, the whole concept of listeners is based on this pattern. For example, you can define a listener for a button in a UI and if the button is selected, the listener is notified and performs a certain action. In this case, the ActionListener is the Observer and the button is your Subject. -
All Servlet Event and Listeners e.g.
ServletContextEvent
andServletContextListener
. TheServletContextEvent
is fired when web application is deployed on the server. If you want to perform some action at the time of deploying the web application such as creating database connection, creating all the tables of the project etc, you need to implementServletContextListener
interface and provide the implementation of its methods. -
javax.servlet.http.HttpSessionBindingListener
-
javax.servlet.http.HttpSessionAttributeListener
-
javax.faces.event.PhaseListener
- Java Message Service (JMS) uses Observer Design Pattern along with Mediator Design Pattern to allow applications to subscribe and publish data to other applications.
That's all for this topic. If you guys have any suggestions or queries, feel free to drop a comment. We would be happy to add that in our post. You can also contribute your articles by creating contributor account here.
Happy Learning 🙂
If you like the content on CodePumpkin and if you wish to do something for the community and the planet Earth, you can donate to our campaign for planting more trees at CodePumpkin Cauvery Calling Campaign.
We may not get time to plant a tree, but we can definitely donate ₹42 per Tree.
About the Author
Tags: Behavioral Design Pattern, Design Patterns, Java
Comments and Queries
If you want someone to read your code, please put the code inside <pre><code> and </code></pre> tags. For example:<pre><code class="java"> String foo = "bar"; </code></pre>For more information on supported HTML tags in disqus comment, click here.