Observer

Observer is a behavioral design pattern. In this pattern our object, which is observable, contains a collection of observers and notifies them every time when observed state has changed or observed event has happened. This is a subscription mechanism. Let’s see this pattern in real life example. Let’s assume that we have an object with weather forecast and two other objects that observe this object. Whenever weather forecast changes we need to notify observers to take needed actions. For this task we need to have an interface Observable with three methods. First one for registering new observers, second one for unregistering observers and third one for notifying observers. I have made two packages for this task. First one „weather” which contains observable objects, in this example there will be only one observable object. And second package that I called „news” with two objects that will be observing our object with weather forecast.

package ObserverTask.weather;
import ObserverTask.news.Observer;

public interface Observable {
void registerObserver(Observer observer);
void unregisterObserver(Observer observer);
void notifyObservers();
}

In registerObserver method we will be passing an object which implemets Observer interface and we will be adding this new observer object to our list of observers. In unregisterObserver method we will be passing an observer object that does not need to observe our weather forecast any more. And finally we need to implement notifyObservers method to notify every observer and make him to take needed action. All right, let’s define an Observer interface with one method needed to be implemented. This method I called updateForecast and we will be passing a WeatherForecast object which will contain temperature and pressure that will be changing.

package ObserverTask.news;
import ObserverTask.weather.WeatherForecast;

public interface Observer {
void updateForecast(WeatherForecast weatherForecast);
}

We will have two observers. First one will be TvNews which will be reporting weather in TV and second one will be InternetNews which will be reporting weather in internet. Let’s create these two classes and implement our method from Observer interface.

package ObserverTask.news;
import ObserverTask.weather.WeatherForecast;

public class TvNews implements Observer {
@Override
public void updateForecast(WeatherForecast weatherForecast) {
System.out.println("TV - new weather forecast - temperature: " + weatherForecast.getTemperature() + " degrees, pressure: " + weatherForecast.getPressure() + " hPa.");
}
}
package ObserverTask.news;
import ObserverTask.weather.WeatherForecast;

public class InternetNews implements Observer {
@Override
public void updateForecast(WeatherForecast weatherForecast) {
System.out.println("Internet - new weather forecast - temperature: " + weatherForecast.getTemperature() + " degrees, pressure: " + weatherForecast.getPressure() + " hPa.");
}
}

And our observable class. It will contain three private attributes, temperature, pressure and set of observers. We will define a constructor and will be passing a temperature and pressure while creating a new object of this class. Then we need to define getters and setters for getting and setting temperature and pressure. After that we need to implement three methods from Observable interface, which are registerObserver, unregisterObserver and notifyObservers. And finally we need to create an updateForecast method which will be setting new temperature, pressure and will be notifying observers.

package ObserverTask.weather;
import ObserverTask.news.Observer;
import java.util.HashSet;
import java.util.Set;

public class WeatherForecast implements Observable {
private int temperature;
private int pressure;
private Set<Observer> registeredObservers = new HashSet<Observer>();

public WeatherForecast(int temperature, int pressure) {
this.temperature = temperature;
this.pressure = pressure;
}
public int getTemperature() {
return temperature;
}
public void setTemperature(int temperature) {
this.temperature = temperature;
}
public int getPressure() {
return pressure;
}
public void setPressure(int pressure) {
this.pressure = pressure;
}

@Override
public void registerObserver(Observer observer) {
registeredObservers.add(observer);
}
@Override
public void unregisterObserver(Observer observer) {
registeredObservers.remove(observer);
}

@Override
public void notifyObservers() {
for(Observer observer : registeredObservers) {
observer.updateForecast(this);
}
}
public void updateForecast(int temperature, int pressure) {
setTemperature(temperature);
setPressure(pressure);
notifyObservers();
}
}

Now let’s see our program in action. First we need to create an object of WeatherForecast class with starting temperature 25 degrees and pressure 1003 hPa. This is our observable object. Then we need to create observers objects of InternetNews and TvNews classes. Now let’s register our observers and notify them to take their actions. Finally we will print a message that we have new forecast but only for internet. In this case we need to unregister our tvNews observer and update our forecast with new temperature and pressure.

import ObserverTask.news.InternetNews;
import ObserverTask.news.TvNews;
import ObserverTask.weather.WeatherForecast;

public class ObserverProgram {
public static void main(String[] args) {
WeatherForecast weatherForecast = new WeatherForecast(25, 1003);
InternetNews internetNews = new InternetNews();
TvNews tvNews = new TvNews();

weatherForecast.registerObserver(internetNews);
weatherForecast.registerObserver(tvNews);
weatherForecast.notifyObservers();

System.out.println();
System.out.println("New weather forecast only for internet.");
weatherForecast.unregisterObserver(tvNews);
weatherForecast.updateForecast(18, 1007);
}
}

Let’s see what happens when we run this program.

Internet – new weather forecast – temperature: 25 degrees, pressure: 1003 hPa.
TV – new weather forecast – temperature: 25 degrees, pressure: 1003 hPa.

New weather forecast only for internet.
Internet – new weather forecast – temperature: 18 degrees, pressure: 1007 hPa.

Process finished with exit code 0

Everything went like expected. We have a message in internet and in TV and after unregistering observer and updating forecast we see new message only in internet. In above example we can see how we can use the observer design pattern. We can easily add new objects that will be watching state of our observable object and remove them when they don’t need to.

Leave a Comment

Twój adres e-mail nie zostanie opublikowany. Wymagane pola są oznaczone *

Scroll to Top