Open In App

Observer Method Design Pattern in Java

Observer Design Pattern is a behavioral design pattern where an object, known as the subject, maintains a list of its dependents, called observers, that are notified of any changes in the subject’s state. This pattern is often used to implement distributed event handling systems.

How We can implement the Observer Method Design Pattern in Java?

Basically, in Java, the Observer pattern is implemented using the ‘java.util.Observer’ interface and the ‘java.util.Observable’ class. However, it’s important to note that the Observable class is considered somewhat outdated, and the ‘java.util’ package doesn’t provide a modern and flexible implementation of the Observer pattern.

In other words, the Observer Pattern is a behavioral design pattern that defines a one-to-many dependency between objects so that when one object changes state, all its dependents are notified and updated automatically. This pattern is commonly used to implement distributed event handling systems.



Key Concepts of Observer Method Design Pattern

The key concepts of the Observer Pattern are:

Example for Observer Method Design Pattern in Java

Problem Statement

Let’s consider a simple weather monitoring system where we have a ‘WeatherStation’ as the subject, and various display devices (observers) like ‘CurrentConditionsDisplay’ and ‘StatisticsDisplay’ that want to be notified whenever the weather changes.

Explanation of Problem :

In this Problem:

So this problem shows the flexibility of the Observer Pattern, allowing for a loosely coupled relationship between the subject and its observers.

Step Wise Implementation of above Problem:

Subject (Observable):

This is the object that maintains a list of observers and notifies us of any changes. In our case, it’s the ‘WeatherStation’ class.




// Subject (Observable)
class WeatherStation {
    private List<Observer> observers = new ArrayList<>();
    private float temperature;
 
    public void addObserver(Observer observer) {
        observers.add(observer);
    }
 
    public void removeObserver(Observer observer) {
        observers.remove(observer);
    }
 
    public void setTemperature(float temperature) {
        this.temperature = temperature;
        notifyObservers();
    }
 
    private void notifyObservers() {
        for (Observer observer : observers) {
            observer.update(temperature);
        }
    }
}

Observer:

This is the observer class which is implemented by concrete observer class. ‘ConcreteObserver’ is an implementation of the ‘Observer’ interface.

The ‘update’ method is called whenever the observed object’s state changes.




// Observer
interface Observer {
    void update(float temperature);
}

Concrete Observer:

These are the classes that implement the Observer interface. In our case, ‘CurrentConditionsDisplay’ and ‘StatisticsDisplay’.




// Concrete Observer
class CurrentConditionsDisplay implements Observer {
    private float temperature;
 
    @Override
    public void update(float temperature) {
        this.temperature = temperature;
        display();
    }
 
    private void display() {
        System.out.println("Current Conditions Display: Temperature = " + temperature);
    }
}
 
// Concrete Observer
class StatisticsDisplay implements Observer {
    private float temperature;
 
    @Override
    public void update(float temperature) {
        this.temperature = temperature;
        display();
    }
 
    private void display() {
        System.out.println("Statistics Display: Temperature = " + temperature);
    }
}

Main Program :

This main class is used to give inputs to the problem and called the observer methods declared above, in out case the main class is ‘ObserverPatternExample’.




// Main class
public class ObserverPatternExample {
    public static void main(String[] args) {
        WeatherStation weatherStation = new WeatherStation();
 
        CurrentConditionsDisplay currentConditionsDisplay = new CurrentConditionsDisplay();
        StatisticsDisplay statisticsDisplay = new StatisticsDisplay();
 
        weatherStation.addObserver(currentConditionsDisplay);
        weatherStation.addObserver(statisticsDisplay);
 
        // Simulate a change in temperature
        weatherStation.setTemperature(25.5f);
        // Output:
        // Current Conditions Display: Temperature = 25.5
        // Statistics Display: Temperature = 25.5
 
        // Simulate another change in temperature
        weatherStation.setTemperature(30.0f);
        // Output:
        // Current Conditions Display: Temperature = 30.0
        // Statistics Display: Temperature = 30.0
 
        // Remove an observer
        weatherStation.removeObserver(currentConditionsDisplay);
 
        // Simulate another change in temperature
        weatherStation.setTemperature(28.0f);
        // Output:
        // Statistics Display: Temperature = 28.0
    }
}

Overall Code Implementation of above Problem




import java.util.ArrayList;
import java.util.List;
 
// Subject (Observable)
class WeatherStation {
    private List<Observer> observers = new ArrayList<>();
    private float temperature;
 
    public void addObserver(Observer observer) {
        observers.add(observer);
    }
 
    public void removeObserver(Observer observer) {
        observers.remove(observer);
    }
 
    public void setTemperature(float temperature) {
        this.temperature = temperature;
        notifyObservers();
    }
 
    private void notifyObservers() {
        for (Observer observer : observers) {
            observer.update(temperature);
        }
    }
}
 
// Observer
interface Observer {
    void update(float temperature);
}
 
// Concrete Observer
class CurrentConditionsDisplay implements Observer {
    private float temperature;
 
    @Override
    public void update(float temperature) {
        this.temperature = temperature;
        display();
    }
 
    private void display() {
        System.out.println("Current Conditions Display: Temperature = " + temperature);
    }
}
 
// Concrete Observer
class StatisticsDisplay implements Observer {
    private float temperature;
 
    @Override
    public void update(float temperature) {
        this.temperature = temperature;
        display();
    }
 
    private void display() {
        System.out.println("Statistics Display: Temperature = " + temperature);
    }
}
 
// Main class
public class ObserverPatternExample {
    public static void main(String[] args) {
        WeatherStation weatherStation = new WeatherStation();
 
        CurrentConditionsDisplay currentConditionsDisplay = new CurrentConditionsDisplay();
        StatisticsDisplay statisticsDisplay = new StatisticsDisplay();
 
        weatherStation.addObserver(currentConditionsDisplay);
        weatherStation.addObserver(statisticsDisplay);
 
        // Simulate a change in temperature
        weatherStation.setTemperature(25.5f);
        // Output:
        // Current Conditions Display: Temperature = 25.5
        // Statistics Display: Temperature = 25.5
 
        // Simulate another change in temperature
        weatherStation.setTemperature(30.0f);
        // Output:
        // Current Conditions Display: Temperature = 30.0
        // Statistics Display: Temperature = 30.0
 
        // Remove an observer
        weatherStation.removeObserver(currentConditionsDisplay);
 
        // Simulate another change in temperature
        weatherStation.setTemperature(28.0f);
        // Output:
        // Statistics Display: Temperature = 28.0
    }
}

Output
Current Conditions Display: Temperature = 25.5
Statistics Display: Temperature = 25.5
Current Conditions Display: Temperature = 30.0
Statistics Display: Temperature = 30.0
Statistics Display: Temperat...

Diagrammatic Representation of above Problem statement:

There are four main components of the observer method pattern are:

Working of observer Pattern

Use Cases of Observer Method Design Pattern

Basically, this pattern is widely used in software development for implementing distributed event handling systems. So let’s see some common use cases for the Observer Pattern:

Advantage of Observer Method Design Pattern

The primary advantage of the Observer Pattern lies in its ability to establish a loosely coupled design between the subject (the object that is being observed) and its observers (the objects that are interested in its state). Here are some key advantages:

Disadvantage of Observer Method Design Pattern

While the Observer Pattern offers several advantages, it’s important to be aware of potential disadvantages or challenges associated with its implementation:


Article Tags :