What is an observer design pattern

The Observer pattern is a behavioral design pattern that  allows an object (an Observer) to watch another object (a Subject). The subject and observer to have a publish/subscribe relationship. Observers can register to receive events from the Subject.

Some of the practical uses of observer pattern are:

  • When a change to one object requires changing of others, and you don’t know how many objects need to be changed.
  • When an object should be able to notify other objects without making assumptions about who these objects are and not tightly coupling them.
  • When a report is received or an event occurs, a message needs to be sent to the subscribed handlers.

Examples:

  • Programming Swing based GUI applications where the listeners register them with events like button click, property change, etc.
  • Programming a stock market application to know when the price of a stock changes.
  • Programming a order placement or trading application to know the status changes like pending, filled, shipped, rejected, etc.

So, whenever you want to have the state change or other information, instead of polling every few second, register the observers with a subject.

 

Here is some pseudo code of this third scenario

STEP 1: Define the Subject and Observer interfaces

This is the subject interface

package com;

 

public interface ReportExecutor {

public void addHandler(ReportHandler rh);

public void removeHandler(ReportHandler rh);

public void processReport(String message);

}

This is the observer interface

package com;

 

public interface ReportHandler {

//handles report

public void handleMessage(String message);

}

STEP 2: Define the concrete subject and observers

The concrete subject

package com;

 

import java.util.ArrayList;

import java.util.List;

 

public class SalesReportExecutor implements ReportExecutor {

 

//list of observers that register their interest in SalesReport

private List<reporthandler> reportHandlers = new ArrayList<reporthandler>();

@Override

public void addHandler(ReportHandler rh) {

reportHandlers.add(rh);

}

@Override

public void processReport(String message) {

for (ReportHandler reportHandler : reportHandlers) {

reportHandler.handleMessage(message);

}

}

@Override

public void removeHandler(ReportHandler rh) {

reportHandlers.remove(rh);

}

}

The concrete observers

package com;

 

public class LoggingReportHandler implements ReportHandler {

 

@Override

public void handleMessage(String message) {

//handles report by formatting and printing

System.out.println(“Logging report  ” + message);

}

}

 

package com;

 

public class EmailReportHandler implements ReportHandler {

 

@Override

public void handleMessage(String message) {

//handles the report by formatting it differently and emailing.

System.out.println(“Emailing report ” + message);

//logic to email report.

}

}

 

STEP 3: Finally, the JMS listener class that uses the subject. The JMS Listener class listens on a queue for presence of a report.

package com.mgl.mts.fix;

 

import javax.jms.Message;

import javax.jms.TextMessage;

 

public class MyAppListener {

 

public void onMessage(Message message) {

if (message instanceof TextMessage) {

 

ReportExecutor executor = new SalesReportExecutor();

executor.addHandler(new LoggingReportHandler());

executor.addHandler(new EmailReportHandler());

executor.processReport(message.toString());

 

} else {

throw new IllegalArgumentException(“Message must be of type TextMessage”);

}

}

}