Tutorial

Observer Design Pattern in Java

Published on August 3, 2022
author

Pankaj

Observer Design Pattern in Java

Observer 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. In observer pattern, the object that watch on the state of another object are called Observer and the object that is being watched is called Subject.

Observer Design Pattern

observer pattern, observer design pattern, observer design pattern in java, observer pattern java According to GoF, observer design pattern intent is;

Define a one-to-many dependency between objects so that when one object changes state, all its dependents are notified and updated automatically.

Subject contains a list of observers to notify of any change in it’s state, so it should provide methods using which observers can register and unregister themselves. Subject also contain a method to notify all the observers of any change and either it can send the update while notifying the observer or it can provide another method to get the update. Observer should have a method to set the object to watch and another method that will be used by Subject to notify them of any updates. Java provides inbuilt 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. Java Message Service (JMS) uses Observer design pattern along with Mediator pattern to allow applications to subscribe and publish data to other applications. Model-View-Controller (MVC) frameworks also use Observer pattern where Model is the Subject and Views are observers that can register to get notified of any change to the model.

Observer Pattern Java Example

For our observer pattern java program example, we would implement a simple topic and observers can register to this topic. Whenever any new message will be posted to the topic, all the registers observers will be notified and they can consume the message. Based on the requirements of Subject, here is the base Subject interface that defines the contract methods to be implemented by any concrete subject.

package com.journaldev.design.observer;

public interface Subject {

	//methods to register and unregister observers
	public void register(Observer obj);
	public void unregister(Observer obj);
	
	//method to notify observers of change
	public void notifyObservers();
	
	//method to get updates from subject
	public Object getUpdate(Observer obj);
	
}

Next we will create contract for Observer, there will be a method to attach the Subject to the observer and another method to be used by Subject to notify of any change.

package com.journaldev.design.observer;

public interface Observer {
	
	//method to update the observer, used by subject
	public void update();
	
	//attach with subject to observe
	public void setSubject(Subject sub);
}

Now our contract is ready, let’s proceed with the concrete implementation of our topic.

package com.journaldev.design.observer;

import java.util.ArrayList;
import java.util.List;

public class MyTopic implements Subject {

	private List<Observer> observers;
	private String message;
	private boolean changed;
	private final Object MUTEX= new Object();
	
	public MyTopic(){
		this.observers=new ArrayList<>();
	}
	@Override
	public void register(Observer obj) {
		if(obj == null) throw new NullPointerException("Null Observer");
		synchronized (MUTEX) {
		if(!observers.contains(obj)) observers.add(obj);
		}
	}

	@Override
	public void unregister(Observer obj) {
		synchronized (MUTEX) {
		observers.remove(obj);
		}
	}

	@Override
	public void notifyObservers() {
		List<Observer> observersLocal = null;
		//synchronization is used to make sure any observer registered after message is received is not notified
		synchronized (MUTEX) {
			if (!changed)
				return;
			observersLocal = new ArrayList<>(this.observers);
			this.changed=false;
		}
		for (Observer obj : observersLocal) {
			obj.update();
		}

	}

	@Override
	public Object getUpdate(Observer obj) {
		return this.message;
	}
	
	//method to post message to the topic
	public void postMessage(String msg){
		System.out.println("Message Posted to Topic:"+msg);
		this.message=msg;
		this.changed=true;
		notifyObservers();
	}

}

The method implementation to register and unregister an observer is very simple, the extra method is postMessage() that will be used by client application to post String message to the topic. Notice the boolean variable to keep track of the change in the state of topic and used in notifying observers. This variable is required so that if there is no update and somebody calls notifyObservers() method, it doesn’t send false notifications to the observers. Also notice the use of synchronization in notifyObservers() method to make sure the notification is sent only to the observers registered before the message is published to the topic. Here is the implementation of Observers that will watch over the subject.

package com.journaldev.design.observer;

public class MyTopicSubscriber implements Observer {
	
	private String name;
	private Subject topic;
	
	public MyTopicSubscriber(String nm){
		this.name=nm;
	}
	@Override
	public void update() {
		String msg = (String) topic.getUpdate(this);
		if(msg == null){
			System.out.println(name+":: No new message");
		}else
		System.out.println(name+":: Consuming message::"+msg);
	}

	@Override
	public void setSubject(Subject sub) {
		this.topic=sub;
	}

}

Notice the implementation of update() method where it’s calling Subject getUpdate() method to get the message to consume. We could have avoided this call by passing message as argument to update() method. Here is a simple test program to consume our topic implementation.

package com.journaldev.design.observer;

public class ObserverPatternTest {

	public static void main(String[] args) {
		//create subject
		MyTopic topic = new MyTopic();
		
		//create observers
		Observer obj1 = new MyTopicSubscriber("Obj1");
		Observer obj2 = new MyTopicSubscriber("Obj2");
		Observer obj3 = new MyTopicSubscriber("Obj3");
		
		//register observers to the subject
		topic.register(obj1);
		topic.register(obj2);
		topic.register(obj3);
		
		//attach observer to subject
		obj1.setSubject(topic);
		obj2.setSubject(topic);
		obj3.setSubject(topic);
		
		//check if any update is available
		obj1.update();
		
		//now send message to subject
		topic.postMessage("New Message");
	}

}

When we run above program, we get following output.

Obj1:: No new message
Message Posted to Topic:New Message
Obj1:: Consuming message::New Message
Obj2:: Consuming message::New Message
Obj3:: Consuming message::New Message

Java Observer Pattern Class Diagram

observer pattern, observer pattern java, observer design pattern Observer design pattern is also called as publish-subscribe pattern. Some of it’s implementations are;

  • java.util.EventListener in Swing
  • javax.servlet.http.HttpSessionBindingListener
  • javax.servlet.http.HttpSessionAttributeListener

That’s all for Observer design pattern in java, I hope you liked it. Share your love with comments and by sharing it with others.

Thanks for learning with the DigitalOcean Community. Check out our offerings for compute, storage, networking, and managed databases.

Learn more about our products

About the author(s)

Category:
Tutorial

While we believe that this content benefits our community, we have not yet thoroughly reviewed it. If you have any suggestions for improvements, please let us know by clicking the “report an issue“ button at the bottom of the tutorial.

Still looking for an answer?

Ask a questionSearch for more help

Was this helpful?
 
JournalDev
DigitalOcean Employee
DigitalOcean Employee badge
January 3, 2014

Thanks for your post. You describe all topics very well.

- Jeni

    JournalDev
    DigitalOcean Employee
    DigitalOcean Employee badge
    January 17, 2014

    Explanation is very good

    - sushil

      JournalDev
      DigitalOcean Employee
      DigitalOcean Employee badge
      February 11, 2014

      Thank for your explanation. But I still have a confusing. As you said: “//synchronization is used to make sure any observer registered after message is received is not notified” in comment of class my topic, the synchronization is used for that purpose. But as my understanding about synchronization, the method “public void register(Observer obj)” and method "public void notifyObservers() " still can be run parallel. It means the observers that registered after message is received also can be notified.

      - Vinh Bui

      JournalDev
      DigitalOcean Employee
      DigitalOcean Employee badge
      February 12, 2014

      Very nice observation, yes you are correct. I have updated the register and deregister methods to use synchronization on MUTEX object, now when message is getting sent to the registered observers, it will not be sent to any observer registered after the message is received.

      - Pankaj

        JournalDev
        DigitalOcean Employee
        DigitalOcean Employee badge
        February 16, 2014

        Very well explained. Thanks…

        - Savi

          JournalDev
          DigitalOcean Employee
          DigitalOcean Employee badge
          March 21, 2014

          Thanks for your effort i really learned from it but your line (this.observers=new ArrayList();) it need to enhanced to (this.observers = new ArrayList();) Thanks, Mohammed Gamal Software Engineer

          - mohammed

            JournalDev
            DigitalOcean Employee
            DigitalOcean Employee badge
            June 10, 2014

            Very Good Explanation !

            - Ashish Patel

              JournalDev
              DigitalOcean Employee
              DigitalOcean Employee badge
              July 22, 2014

              Thanks for this explanation! The only thing I don’t completely get is the need of the setSubject method in the Observer. Could you please explain?

              - Gerardo

              JournalDev
              DigitalOcean Employee
              DigitalOcean Employee badge
              August 5, 2014

              Hi Gerardo The object of an observer needs a subject to monitor, so the observer object should have a method to assign that subject to it. So that whenever a change occurs in the subject the observer gets to know it. So is the need of that setSubject method.

              - Akash kumar

              JournalDev
              DigitalOcean Employee
              DigitalOcean Employee badge
              September 3, 2016

              Instead of having a setSubject method on the Observer side, would it not be better if the subject is simply passed as an argument in the update method of the observer . Something like update(Subject sub), wherein this would be passed as argument from the subject’s side while calling the method.

              - Nikhil Verma

                JournalDev
                DigitalOcean Employee
                DigitalOcean Employee badge
                October 1, 2014

                How to run this program using netbeans. Please explain it.

                - Prince

                  JournalDev
                  DigitalOcean Employee
                  DigitalOcean Employee badge
                  January 2, 2015

                  Very good and simple explanation.

                  - md farooq

                    JournalDev
                    DigitalOcean Employee
                    DigitalOcean Employee badge
                    February 23, 2015

                    i didn’t understand why the method getUpdate(Obserever obj) needs the Observer reference parameter since it doesnt uses it.

                    - yuval

                      JournalDev
                      DigitalOcean Employee
                      DigitalOcean Employee badge
                      February 26, 2015

                      The register() in MyTopic class should also call the Observer’s setSubject() passing ‘this’ as a parameter thereby abstracting, the attaching of the subject to the observer, from the client code. The client code should only need to register the observer to the topic. Importance of passing observer as a parameter to the MyTopic’s getUpdate() can be demonstrated by having a call back method in Observer interface.

                      - Jasvinder Singh

                        JournalDev
                        DigitalOcean Employee
                        DigitalOcean Employee badge
                        April 11, 2015

                        Hi, I would like to know whether same implementation can be used for stocks exchange , that is there are stream of stocks are coming in and the clients are waiting on the other side to see the current stock value of a particular company

                        - Karan

                          JournalDev
                          DigitalOcean Employee
                          DigitalOcean Employee badge
                          May 9, 2015

                          Hi, Pankaj!! Thx for tutorials, like them much. Bur this one seems to be confusing a little. Here is more clear one. Implement this, if you like it.

                          - Oleg

                            JournalDev
                            DigitalOcean Employee
                            DigitalOcean Employee badge
                            May 11, 2015

                            After spending so much time on many tutorials, this was the best. Great explaination.

                            - Darpan

                              JournalDev
                              DigitalOcean Employee
                              DigitalOcean Employee badge
                              January 4, 2016

                              Excellent explanation and it helped me lot to understand what is Observer design pattern. Thanks a lot.

                              - Biswajit Mohapatra

                                JournalDev
                                DigitalOcean Employee
                                DigitalOcean Employee badge
                                February 23, 2016

                                Very good explanation

                                - sridhar

                                  JournalDev
                                  DigitalOcean Employee
                                  DigitalOcean Employee badge
                                  March 31, 2016

                                  Thanks Mr Pankaj. I read design pattern from multiple sites, but your tutorial was more useful and was best. keep doing your best!

                                  - Khosro Makari

                                    JournalDev
                                    DigitalOcean Employee
                                    DigitalOcean Employee badge
                                    May 9, 2016

                                    Hi, the method does not use the passed in variable: Observer obj public Object getUpdateMsg(Observer obj) Is it necessary to rewrite it as ‘public Object getUpdateMsg()’ ?

                                    - Ivan

                                      JournalDev
                                      DigitalOcean Employee
                                      DigitalOcean Employee badge
                                      June 16, 2016

                                      Great article, exactly what I was looking for. Thank you, and keep up the good work.

                                      - Jason Alls

                                      JournalDev
                                      DigitalOcean Employee
                                      DigitalOcean Employee badge
                                      June 16, 2016

                                      Glad you liked it Jason.

                                      - Pankaj

                                        JournalDev
                                        DigitalOcean Employee
                                        DigitalOcean Employee badge
                                        June 19, 2016

                                        Thanks for such a good explanation. Keep up the good work.

                                        - Sumit

                                          JournalDev
                                          DigitalOcean Employee
                                          DigitalOcean Employee badge
                                          July 16, 2016

                                          Thanks for the nice article. But I wanted to check/know the reason why synchronization is required in this example? Is it not an overkill?

                                          - Ankit

                                            JournalDev
                                            DigitalOcean Employee
                                            DigitalOcean Employee badge
                                            October 27, 2016

                                            Crystal clear. Useful for both the beginners and advanced level developers.

                                            - Subhash Kumar

                                              JournalDev
                                              DigitalOcean Employee
                                              DigitalOcean Employee badge
                                              January 4, 2017

                                              I think this code has a flaw. If we set the message once and then do not set again and then check if there is any update, then according to the code the old msg is not null and it will tell that the update actually happened.

                                              - Faizuddin Ahmed Shaik

                                                JournalDev
                                                DigitalOcean Employee
                                                DigitalOcean Employee badge
                                                January 2, 2018

                                                Awesome article, such a simple and easy one to understand it.

                                                - Krishna

                                                  JournalDev
                                                  DigitalOcean Employee
                                                  DigitalOcean Employee badge
                                                  January 24, 2018

                                                  Really good article. Much better than others which are out there

                                                  - Anand

                                                    JournalDev
                                                    DigitalOcean Employee
                                                    DigitalOcean Employee badge
                                                    March 9, 2018

                                                    It would be helpful to put a comment for why public void unregister(Observer obj) has a synchronized block, It is because you cannot add elements to arraylist and also remove elements from it at the same time. It will give a java.util.ConcurrentModificationException.

                                                    - John

                                                      JournalDev
                                                      DigitalOcean Employee
                                                      DigitalOcean Employee badge
                                                      March 9, 2018

                                                      You said that “Subject also contain a method to notify all the observers of any change and either it can send the update while notifying the observer or it can provide another method to get the update.” How do we decide which implementation to use ? I am guessing that if some of the observers only care that update has happened, but don’t care what was the update, then just update() is useful. If some are interested in what was updated, then update(Object updateInfo) makes sense. Also, why are we passing observer inside getUpdate(Observer obj) ? Maybe observable can use that to track which all observers got the message ?

                                                      - John

                                                        JournalDev
                                                        DigitalOcean Employee
                                                        DigitalOcean Employee badge
                                                        August 14, 2018

                                                        What is MUTEX object used for

                                                        - Kunal Dada

                                                          JournalDev
                                                          DigitalOcean Employee
                                                          DigitalOcean Employee badge
                                                          July 14, 2019

                                                          Thank you a lot

                                                          - omid

                                                            JournalDev
                                                            DigitalOcean Employee
                                                            DigitalOcean Employee badge
                                                            October 6, 2019

                                                            thanks for this.very well explained

                                                            - Jay

                                                              Try DigitalOcean for free

                                                              Click below to sign up and get $200 of credit to try our products over 60 days!

                                                              Sign up

                                                              Join the Tech Talk
                                                              Success! Thank you! Please check your email for further details.

                                                              Please complete your information!

                                                              Become a contributor for community

                                                              Get paid to write technical tutorials and select a tech-focused charity to receive a matching donation.

                                                              DigitalOcean Documentation

                                                              Full documentation for every DigitalOcean product.

                                                              Resources for startups and SMBs

                                                              The Wave has everything you need to know about building a business, from raising funding to marketing your product.

                                                              Get our newsletter

                                                              Stay up to date by signing up for DigitalOcean’s Infrastructure as a Newsletter.

                                                              New accounts only. By submitting your email you agree to our Privacy Policy

                                                              The developer cloud

                                                              Scale up as you grow — whether you're running one virtual machine or ten thousand.

                                                              Get started for free

                                                              Sign up and get $200 in credit for your first 60 days with DigitalOcean.*

                                                              *This promotional offer applies to new accounts only.