Java listener pattern

Samantha 57 Published: 09/28/2024

Java listener pattern

I'll respond in English for now.

Java's Listener Pattern is a design pattern that provides a way to handle events or notifications from other objects. It's also known as the Observer pattern, and it's commonly used in systems where multiple objects need to be notified about changes in the state of another object.

Here's how it works:

Subject (Observable): The object being observed is called the Subject (or Observable). This object maintains a list of its listeners (observers) and provides methods for adding, removing, or notifying them. Observer (Listener): The objects that need to be notified about changes in the state of the Subject are called Observers (or Listeners). Each observer implements an interface with a single method that's called when the subject notifies it.

Here's an example of how the Listener pattern can be implemented in Java:

// Subject interface

interface Observer {

void update(String message);

}

// Concrete Subject class

class WeatherStation implements Observer {

private List observers = new ArrayList<>();

private String temperature;

public void registerObserver(Observer observer) {

observers.add(observer);

}

public void removeObserver(Observer observer) {

observers.remove(observer);

}

public void notifyObservers(String message) {

for (Observer observer : observers) {

observer.update(message);

}

}

public void setTemperature(String temperature) {

this.temperature = temperature;

notifyObservers("Temperature: " + temperature);

}

}

// Concrete Observer class

class WeatherRadio implements Observer {

@Override

public void update(String message) {

System.out.println("Weather radio received: " + message);

}

}

public class Main {

public static void main(String[] args) {

// Create a weather station and register two observers (radios)

WeatherStation weatherStation = new WeatherStation();

weatherStation.registerObserver(new WeatherRadio());

weatherStation.registerObserver(new WeatherRadio());

// Set the temperature

weatherStation.setTemperature("20°C");

// Unregister one of the radios

weatherStation.removeObserver(new WeatherRadio());

weatherStation.setTemperature("22°C");

}

}

In this example, WeatherStation is the Subject (Observable) and WeatherRadio is an Observer (Listener). When you set a new temperature using setTemperature, all registered observers are notified with a message describing the change.

Benefits of the Listener pattern:

Decouples objects: The subject doesn't know which specific observer objects exist or how they respond. This decoupling makes it easier to modify or replace either side without affecting the other. Simplifies code: By having one place (the subject) manage notifications, you avoid scattering notification logic throughout your system.

Common use cases for the Listener pattern:

Event-driven systems: When multiple objects need to respond differently to various events. Real-time data updates: When a central repository needs to notify connected clients about changes in its state. Asynchronous processing: When you want to process tasks without blocking other parts of your system.

Keep an eye out for more design patterns and Java best practices!

Observer and Observable in Java

I'd be happy to explain Observer and Observable patterns in Java.

Observer Pattern

The Observer pattern is a design pattern that allows objects to notify other objects about changes to their state. It's used when one or more objects are interested in the state of another object, but don't depend on each other too closely. This pattern is also known as the "Publish-Subscribe" model.

Here's how it works:

An Observable (also known as Subject) object maintains a list of observers. Observer objects register with the observable to receive notifications when its state changes. When an observable changes, it notifies all its registered observers by calling their notify method.

In Java, this pattern is implemented using interfaces and abstract classes. The java.util.Observable class provides methods for adding and removing observers.

Observable (Subject) Class

This class maintains a list of observers and provides methods to add or remove them:

public class Observable {

private List observerList;

public Observable() {

observerList = new ArrayList<>();

}

public void addObserver(Observer o) {

observerList.add(o);

}

public void deleteObserver(Observer o) {

int i = observerList.indexOf(o);

if (i != -1) {

observerList.remove(i);

}

}

protected void notifyObservers() {

for (Observer obs : observerList) {

obs.update();

}

}

}

Observer Interface

This interface defines the update method that's called when an observable changes:

public interface Observer {

void update();

}

Example Usage

Here's a simple example where we have an Observable (WeatherStation) and several observers (TemperatureSensor, HumiditySensor, WindSpeedSensor). The weather station notifies its observers whenever the temperature, humidity, or wind speed changes:

public class WeatherStation extends Observable {

private double temperature;

private double humidity;

private double windSpeed;

public void setTemperature(double temp) {

if (temperature != temp) {

temperature = temp;

notifyObservers();

}

}

public void setHumidity(double humidity) {

if (this.humidity != humidity) {

this.humidity = humidity;

notifyObservers();

}

}

public void setWindSpeed(double speed) {

if (windSpeed != speed) {

windSpeed = speed;

notifyObservers();

}

}

}

public class TemperatureSensor implements Observer {

@Override

public void update() {

System.out.println("Temperature: " + WeatherStation.getInstance().getTemperature());

}

}

public class HumiditySensor implements Observer {

@Override

public void update() {

System.out.println("Humidity: " + WeatherStation.getInstance().getHumidity());

}

}

public class WindSpeedSensor implements Observer {

@Override

public void update() {

System.out.println("Wind Speed: " + WeatherStation.getInstance().getWindSpeed());

}

}

Benefits

The Observer pattern provides several benefits:

Decouples objects that don't depend on each other closely. Allows for loose coupling between observable and observer classes. Enables multiple observers to receive notifications when an observable changes.

This design pattern is commonly used in Java applications, such as GUI frameworks, event-driven systems, and data streaming systems.