Observer Pattern

Observer Pattern is one of the behavioural design patterns.

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

In this pattern, it is very important to understand below terms

Subject : The object which is being watched is called the subject.

Observer (or) Listener : The objects which are watching the state changes are called observers or listeners

Example :

The best example for Observer pattern is the Event listener in Java

Event is the subject and listener is the observer

There can be many listeners for one event.

Subject :

It contains a list of all observers to whom notification has to be made for any change in the state of Subject.

Subject should provide a method using which observers can register/unregister themselves for the notification of subject’s state change.

Subject should also provide a method to notify all the observers if any change in its state.

Observer :

Observer should provide a method to set the object to watch the Subject’s state change

Observer should also provide another method that will be used by Subject to notify Observer for any change in its state.

Java provides inbuilt mechanism for implementing Observer pattern through java.util.Observable class and java.util.Observer interface.

However it’s not best option as 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.

Let’s see how to implement Observer pattern

Step 1

Create an interface to represent Subject

  1. package com.kb.observer;
  2.  
  3. public interface Subject {
  4.    
  5.      public void registerObserver(Observer observer);
  6.  
  7.      public void removeObserver(Observer observer);
  8.  
  9.      public void notifyObservers();
  10.  
  11. }
package com.kb.observer;

public interface Subject {
	
	 public void registerObserver(Observer observer);

     public void removeObserver(Observer observer);

     public void notifyObservers();

}

Step 2

Create an interface to represent Observer

  1. package com.kb.observer;
  2.  
  3. public interface Observer {
  4.     public void update(float temperature,float humudity);
  5.  
  6. }
package com.kb.observer;

public interface Observer {
	public void update(float temperature,float humudity);

}

Step 3

Create a class implementing the Subject

  1. package com.kb.observer;
  2.  
  3. import java.util.ArrayList;
  4. import java.util.List;
  5.  
  6. public class WeatherData implements Subject{
  7.     private float temperature;
  8.     private float humidity;
  9.    
  10.     private List<Observer> observers;
  11.    
  12.     public WeatherData() {
  13.     observers=new ArrayList<>();
  14.     }
  15.  
  16.     @Override
  17.     public void registerObserver(Observer observer) {
  18.         observers.add(observer);
  19.     }
  20.  
  21.     @Override
  22.     public void removeObserver(Observer observer) {
  23.         observers.remove(observer);
  24.        
  25.     }
  26.  
  27.     @Override
  28.     public void notifyObservers() {
  29.         for (Observer observer : observers) {
  30.             observer.update( temperature, humidity);
  31.         }
  32.        
  33.     }
  34.    
  35.     public void weatherChanged(float temperature,float humidity){
  36.         this.temperature=temperature;
  37.         this.humidity=humidity;
  38.         notifyObservers();
  39.     }
  40. }
package com.kb.observer;

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

public class WeatherData implements Subject{
	private float temperature;
	private float humidity;
	
	private List<Observer> observers;
	
	public WeatherData() {
	observers=new ArrayList<>();
	}

	@Override
	public void registerObserver(Observer observer) {
		observers.add(observer);
	}

	@Override
	public void removeObserver(Observer observer) {
		observers.remove(observer);
		
	}

	@Override
	public void notifyObservers() {
		for (Observer observer : observers) {
			observer.update( temperature, humidity);
		}
		
	}
	
	public void weatherChanged(float temperature,float humidity){
		this.temperature=temperature;
		this.humidity=humidity;
		notifyObservers();
	}
}

Step 4

Create a class implementing Observer

  1. package com.kb.observer;
  2.  
  3. public class WeatherDataConsumer implements Observer{
  4.  
  5.     @Override
  6.     public void update(float temperature,float humidity) {
  7.         System.out.println("Changed weather data ");
  8.         System.out.println("temperature -> "+temperature);
  9.         System.out.println("humidity -> "+humidity);
  10.        
  11.     }
  12.  
  13. }
package com.kb.observer;

public class WeatherDataConsumer implements Observer{

	@Override
	public void update(float temperature,float humidity) {
		System.out.println("Changed weather data ");
		System.out.println("temperature -> "+temperature);
		System.out.println("humidity -> "+humidity);
		
	}

}

Step 5

Create a client class to test the pattern

  1. package com.kb.observer;
  2.  
  3. public class ObserverPatternClient {
  4.  
  5.     public static void main(String[] args) {
  6.         WeatherData weatherData = new WeatherData();
  7.        
  8.                 //create observers
  9.                 Observer observer1 = new WeatherDataConsumer();
  10.                 Observer observer2 = new WeatherDataConsumer();
  11.                 Observer observer3 = new WeatherDataConsumer();
  12.                
  13.                 //register observers to the subject
  14.                 weatherData.registerObserver(observer1);
  15.                 weatherData.registerObserver(observer2);
  16.                 weatherData.registerObserver(observer3);
  17.                
  18.                 weatherData.weatherChanged(40, 35);
  19.                
  20.                 weatherData.removeObserver(observer3);
  21.                
  22.                 weatherData.weatherChanged(40, 35);
  23.     }
  24.  
  25. }
package com.kb.observer;

public class ObserverPatternClient {

	public static void main(String[] args) {
		WeatherData weatherData = new WeatherData();
		
				//create observers
				Observer observer1 = new WeatherDataConsumer();
				Observer observer2 = new WeatherDataConsumer();
				Observer observer3 = new WeatherDataConsumer();
				
				//register observers to the subject
				weatherData.registerObserver(observer1);
				weatherData.registerObserver(observer2);
				weatherData.registerObserver(observer3);
				
				weatherData.weatherChanged(40, 35);
				
				weatherData.removeObserver(observer3);
				
				weatherData.weatherChanged(40, 35);
	}

}


In the output, we can see that initially there are 3 observers are registered and hence Subject state change is notifying all 3 observers and So it prints weather data 3 times

After that we removed one observer from Notification list and hence next time we can see its notifying 2 observers.

Important points about Observer pattern


Using the observer pattern a subject can register an unlimited number of observers.

If a new listener wants to register with the subject, no code change in the subject is necessary.

Using the listener pattern decouples the subject from its observers. Only the observers have direct knowledge about the subject.

Observer design pattern is also called as “publish-subscribe pattern”.

Some of its implementations are


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

Advantage of Observer Design Pattern in Java


Loose coupling between observer and “Subject”.

The “Subject” only know the list of observers, it don’t care about how they have their implementation.

All the observers are notified by “Subject” in a single event call

Disadvantage of Observer Design Pattern in Java


• Debugging becomes very difficult because flow of control is implicitly between observers and Subject.

• Another issue is Memory management because subject contains the reference of all the observers, If we do not unregister the observer object, it can create the memory issue.

About the Author

Founder of javainsimpleway.com
I love Java and open source technologies and very much passionate about software development.
I like to share my knowledge with others especially on technology 🙂
I have given all the examples as simple as possible to understand for the beginners.
All the code posted on my blog is developed,compiled and tested in my development environment.
If you find any mistakes or bugs, Please drop an email to kb.knowledge.sharing@gmail.com

Connect with me on Facebook for more updates

Share this article on