Event – Observer pattern

Imagine a situation: you are developing a custom e-commerce framework and are about to put some finishing touches to your order model. The task is to program functionality, which creates an order at the end of the checkout and saves it to the database. You realize that a confirmation email has to be sent and you add the necessary code. Next morning a product manager asks you to send a copy of the e-mail to his address, and you extend your code accordingly. At a meeting in the afternoon the warehouse guy proposes to automate inventory management by sending a message to the warehouse software; and you implement it in your code. Exporting order as an XML file to feed into the shipping system – done. Notifying the purchasing department when the inventory is too low – done too.

After all this you take a look at your order model and its function placeOrder and see it has become an unmaintainable mess. All these diverse and complex tasks just do not fit into the order model. Yet they are essential for the your business and must be implemented. Situations like this are not uncommon. The growing complexity of enterprise applications often results in code that is inflexible and difficult to maintain, and prohibitively expensive to scale.

Event-driven software architecture has evolved to address such problems by decoupling services and service providers. It introduces events – notable milestones in business processes that invoke services, which observe and react to them. Events alert their subscribers about a problem, or an opportunity, or a threshold in the current process flow. An event broadcasted in the system usually consists of an event header and body. The event header contains an ID that is used to locate subscribers, while the body transports information required to process the event. In some systems event headers can also include information on the event type and creator, or a timestamp – whatever data the specifications mandates.

The service providers are independent entities and can be added or removed without affecting objects, whose events they listen to. Event creators have no knowledge of the subscribed service providers and do not depend on them. Similarly service providers are not interested in the internal mechanics of event creators. This allows for extremely flexible, loosely coupled and distributed systems. This advantages, however, come at a price – tracing events and their subscribers can be difficult.

Below is simple example of Event-Observer pattern :

Application : Suppose we want to find out the different versions of given string let say hex ,decimal , octal etc we can apply event observer for this as given below:

Observer.java

abstract class Observer {

protected Subject subject;

public abstract void update();
}

 

Subject.java

public class Subject {

private List<Observer> observers = new ArrayList<Observer>();
private int state;

public int getState() {
return state;
}

public void setState(int state) {
this.state = state;
notifyAllObservers();
}

public void attach(Observer observer) {
observers.add(observer);
}

public void notifyAllObservers() {
for (Observer observer : observers) {
observer.update();
}
}
}

BinaryObserver.java
public class BinaryObserver extends Observer{

public BinaryObserver(Subject subject){
this.subject = subject;
this.subject.attach(this);
}

@Override
public void update() {
System.out.println( “Binary String: ” + Integer.toBinaryString( subject.getState() ) );
}
}

OctalObserver.java

public class OctalObserver extends Observer{

public OctalObserver(Subject subject){
this.subject = subject;
this.subject.attach(this);
}

@Override
public void update() {
System.out.println( “Octal String: ” + Integer.toOctalString( subject.getState() ) );
}
}

 

HexaObserver.java

public class HexaObserver extends Observer {

public HexaObserver(Subject subject) {
this.subject = subject;
this.subject.attach(this);
}

@Override
public void update() {
System.out.println(“Hex String: ” + Integer.toHexString(subject.getState()).toUpperCase());
}
}

 

ObserverPatternDemo.java

public class ObserverPatternDemo {

public static void main(String[] args) {
Subject subject = new Subject();
new HexaObserver(subject);
new OctalObserver(subject);
new BinaryObserver(subject);
System.out.println(“First state change: 15”);
subject.setState(15);
System.out.println(“Second state change: 10”);
subject.setState(10);
}
}

As soon as event is triggered it is propagated to all attached observer. A beautiful design pattern to code!!

 

 

 

 

 

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s