observer design pattern real world example in java

The observer pattern is part of the behavioural design pattern and it defines a one object changes state all of its dependents are notified and updated automatically. The observer design pattern is easy to implement and allows us to add new observers or remove old observers at runtime.

The subject and observers define the one-to-many relationship. The observers are dependent on the subject such that when the subject’s state changes, the observers get notified. Depending on the style of notification, the observer may also be updated with new values.

Lets take an example we had application which would detect breaches based on the historical pattern and multiple components where interested to know when ever there is a breach in the network . Few of the interested components where analytics algorithms, oracle component and also the data was published to a messaging queue to name a few. This is a kind of use case the observer pattern is made for and we will implement the same here.

In observer pattern the subject is the interface which will be used to by the objects to register and de register as the observers.All observers need to implement a observer interface and this interface will usually have one method like publish which will be called by the subject when there is a change in the subject state.

The observer pattern provides an object design where subjects and observers are loosely coupled which helps to achieve a design principle “strive for loosely coupled designs between objects that interact” . Loosely coupled designs allow us to build flexible object oriented systems that can handle change because they minimize the interdependency between objects.

Below is the class diagram we will be working on

Lets code this example

Subject Code

Here AlertObservable is our subject interface which has methods to register,unregister and to notifyObservers when there is a change in the state of the object being observed.


public interface AlertObservable {

public void register(AlertObserver observer);

public void unregister(AlertObserver observer);

public void notifyObservers(Alert alert);

}

PublishAlert is our concrete AlertObservable which is composed of a list of alertObserver which will be updated when there is a new observer is added or existing observer is unregistered . Also when there is a an alert the publish method iterates through the alertObservers list and published the alert into all the observers.


public class PublishAlert implements AlertObservable {

private List<AlertObserver> alertObservers = new ArrayList<AlertObserver>();

public List<AlertObserver> getAlertObservers() {
return alertObservers;
}

@Override
public void register(AlertObserver observer) {
getAlertObservers().add(observer);
}

@Override
public void unregister(AlertObserver observer) {
int index = getAlertObservers().indexOf(observer);
getAlertObservers().remove(index);

}

@Override
public void notifyObservers(Alert alert) {

for (AlertObserver alertObserver : getAlertObservers()) {
alertObserver.publish(alert);

}
}

}

Observer Code

AlertObserver is our observer interface which just have one method to publish the alert into all the observers.


public interface AlertObserver {

public void publish(Alert alert);
}

Concrete alert observers FileAlertSubscriber and OracleAlertSubscriber . I have not added any implementation into the publish method ideally you should have the logic to insert data into the oracle database in the OracleAlertSubscriber and logging into the file in the FileAlertSubscriber.


public class FileAlertSubscriber implements AlertObserver {

private AlertObservable alertObservable;

public FileAlertSubscriber(AlertObservable alertObservable) {
super();
this.alertObservable = alertObservable;
this.alertObservable.register(this);
}

public AlertObservable getAlertObservable() {
return alertObservable;
}

public void setAlertObservable(AlertObservable alertObservable) {
this.alertObservable = alertObservable;
}

@Override
public void publish(Alert alert) {

}
}


public class OracleAlertSubscriber implements AlertObserver {

private AlertObservable alertObservable;

public OracleAlertSubscriber(AlertObservable alertObservable) {
super();
this.alertObservable = alertObservable;
this.alertObservable.register(this);
}

public AlertObservable getAlertObservable() {
return alertObservable;
}

public void setAlertObservable(AlertObservable alertObservable) {
this.alertObservable = alertObservable;
}

@Override
public void publish(Alert alert) {

}

}

Alert domain object

import java.util.List;

public class Alert {

private int subElementId;
private int metricMetadataId;
private int metricMetadataHourlyId;
private float metricValue;

public Alert(int subElementId, int metricMetadataId, int metricMetadataHourlyId, float metricValue,
List<Integer> elementsEffected) {
super();
this.subElementId = subElementId;
this.metricMetadataId = metricMetadataId;
this.metricMetadataHourlyId = metricMetadataHourlyId;
this.metricValue = metricValue;
}

public int getSubElementId() {
return subElementId;
}

public void setSubElementId(int subElementId) {
this.subElementId = subElementId;
}

public int getMetricMetadataId() {
return metricMetadataId;
}

public void setMetricMetadataId(int metricMetadataId) {
this.metricMetadataId = metricMetadataId;
}

public int getMetricMetadataHourlyId() {
return metricMetadataHourlyId;
}

public void setMetricMetadataHourlyId(int metricMetadataHourlyId) {
this.metricMetadataHourlyId = metricMetadataHourlyId;
}

public float getMetricValue() {
return metricValue;
}

public void setMetricValue(float metricValue) {
this.metricValue = metricValue;
}

}

When we detect any alert we should get the common alertObservable which was used when constructing all our observers and notify them as below.

getAlertObservable().notifyObservers(alert);