Saturday, March 3, 2012

Observer Design Pattern in Java

The Observer Pattern works on principle of "Notify Me" when State of Subject (called Observable) changes. This
is a one to many relationship between Subject and Observers/Listeners. The only clause is "Observers" can register-deregister
any time. The loose coupling must be maintained.

Example:     
    Customers clicking "Notify Me" button in fashion sites/mobile items when the item is "Out of Stock".
    When the same item again becomes "In-Stock", all these customers/observers gets email/notified. Here item 
    is called subject/observable.
    
    Stock Market Sites like Sharekhan, Zerodha, India Infoline (observers) updates stock activities like Prices, Traded volumns, 
    Orders    whenever price change happens in Nifty.
    
    ClusterNotification: If a card gets blocked or device is black listed, a notice should be issued (notify should be invoked) among
    all the Servers so they can stop the blocked card transaction.
    
    Rule change in White House (Donald Trump has signed the bill to stop citizens of 7 muslim countries) triggers notifications to all 
    the Observers (Airports, Visa Authorities who are registered with White House) to ban these 7 countries citizens.

    Also called publish-subscribe pattern.
    
    Whether forcasting display system which keeps getting updated from real time data (data comes from Physical machine sensors 
    like "Humidity censors, Temperature censors").

    
Things required to implement Observer Pattern:
1) One Observer interface, which will have update method.
2) One Observable/Subject/RuleSet, which will have register(), unregister(), notifyAll() methods.
3) One Subject Integrator where Subject/RuleSet methods are implemented, like NSE (National Stock Exchange: Sharekhan, 
   Zerodha need to register themselves first).
4,5) 2 Observers which will implement above interface (Sharekhan, Zerodha) for display their prices after update. 
     Note that the Sharekhan and Zerodha Observers must maintain a reference variable of type Subject for calling 
     register, unregister, notifyAll. Because of loose coupling, they can register-unregister independently.
6) Main Program to see all.
7) Total 6 Programs


=============Observer.java============
package designpattern.observerpattern;
public interface Observer {
    public void update(int infySharePrice);
}

===============Subject.java, The RuleSet=============
package designpattern.observerpattern;
public interface Subject {
    public void addObserver(Observer o);
    public void removeObserver(Observer o);
    public void notifyObservers();    
}

===============NSE.java, The integrator===============
package designpattern.observerpattern;
import java.util.ArrayList;
import java.util.List;

public class NSE implements Subject {
    int infosysSharePrice = 1000;  
    public void setInfosysSharePrice(int v) {
        infosysSharePrice = v;
    }
    
    List<Observer> observers = new ArrayList<Observer>(); //To maintain list of registered observers.
    public void addObserver(Observer o){
        observers.add(o);
    }
    public void removeObserver(Observer o) {        
        observers.remove(o);
    }
    public void notifyObservers() {
        for (int i=0; i<observers.size();i++) {
            Observer ob = (Observer)observers.get(i);
            ob.update(infosysSharePrice);
        }
    }
}

===============Sharekhan.java===============
package designpattern.observerpattern;
public class Sharekhan implements Observer {  //This is an Observer
    int latestValue = 0;
    Subject nseRegistration; 

    public Sharekhan(NSE nse) { 
        nseRegistration = nse;
        nseRegistration.addObserver(this);        
    }
    public void update(int value) {
        latestValue = value;
        System.out.println("Sharekhan, Infosys Stock Price=" + latestValue);
    }
    public void unregister(){
        nseRegistration.removeObserver(this);
    }
}

===============Zerodha.java===============
package designpattern.observerpattern;
public class Zerodha implements Observer {  //This is an Observer
    int latestValue = 0;
    Subject nseRegistration; 

    public Zerodha(NSE nse) { 
        nseRegistration = nse;
        nseRegistration.addObserver(this);        
    }
    public void update(int value) {
        latestValue = value;
        System.out.println("Zerodha, Infosys Stock Price=" + latestValue);
    }
}

===============MainProgram.java===============
package designpattern.observerpattern;
public class MainProgram {
    public static void main(String[] args) {
        NSE stockExchangeIntegrator =  new NSE();

        Sharekhan obs1 = new Sharekhan(stockExchangeIntegrator); //Create Observer object, pass integrator
        Observer obs2 = new Zerodha(stockExchangeIntegrator);    //Create Observer object, pass integrator
       
        System.out.println("Initial Price..............");
        stockExchangeIntegrator.notifyObservers();
        
        System.out.println("\nAfter few Days Price..............");
        stockExchangeIntegrator.setInfosysSharePrice(1070);
        stockExchangeIntegrator.notifyObservers();
        
        System.out.println("\nAfter removing Sharekhan observer..............");
        obs1.unregister();             //Sharekhan unregistered now
        stockExchangeIntegrator.setInfosysSharePrice(1100);
        stockExchangeIntegrator.notifyObservers();
    }
}

//Output:
Initial Price..............
Sharekhan, Infosys Stock Price=1000
Zerodha, Infosys Stock Price=1000

After few Days Price..............
Sharekhan, Infosys Stock Price=1070
Zerodha, Infosys Stock Price=1070

After removing Sharekhan observer..............
Zerodha, Infosys Stock Price=1100
=========================================================

No comments:

Post a Comment