Sunday, 1 February 2015

The Observer Design Pattern

Background

Ever subscribed to a blog, news or a RSS feed? If not you should definitely try it out. It saves time of scanning through the whole content to find posts of your interest especially in this information technology times when there is so much data flowing on the internet. Anyway lets see how this works as it would be crucial in understanding the design pattern that we are going to discuss today -  The Observer Design Pattern.


How Observer Pattern Works?

Lets say we have a new website - www.worldNews.com that provides information of events going on in the entire glob. You on the other hand are Cricket fan and really would like to get all updates of cricket matches all over the globe.



One crude way would be go to the sites sports section and check out cricket events like twice a day or more? But if the site provides an RSS feed for cricket news you can simply subscribe to it and whenever news site publishes something about cricket you will directly get the news feed.   




In The Observer Design Pattern world 'Cricket' is the subject and you are the observer. As an observer you register yourself to the Subject and whenever Subject's state gets updated all the registered observers (including you) get notified. You can also de-register yourself from the update.


Lets write a code in Java for above to get a better understanding of Observer pattern. For the record Java provides an in built support for Observer pattern but we will look at it in some time. For now lets do it from very basics.

Definition

Definition for Observer Design pattern as per Wiki is -

The observer pattern is a software design pattern in which an object, called the subject, maintains a list of its dependents, called observers, and notifies them automatically of any state changes, usually by calling one of their methods. It is mainly used to implement distributed event handling systems.

Generic Class Diagram



"Observer" by WikiSolved - Own work. Licensed under Public Domain via Wikimedia Commons.

To the code.....

Lets first create our interfaces and model classes - 

Lets first create Subject interface. Later we will create Cricket subject that implements Subject interface. We write interface so that tomorrow we can add  more subjects like finance, political new etc. For this demo we will just see cricket event.

public interface Subject {
    public void registerObserver(Observer observer);
    public void deregisterObserver(Observer observer);
    public void notifyObservers(Event event);
    public void onNewEvent(Event event);
}

Notice how Subject interface has following three methods - 

  1. registerObserver - Each observer will call this method on the Subject he is interested in and will get registered.
  2. deregisterObserver - Observer may choose to de register from getting updates on a subject. I such cases Observer will call this method.
  3. notifyObservers - Whenever subjects state will change this method will be invoked which will push the updated data to the observers who have registered to that subject.
  4. onNewEvent - This method is called whenever new Event is generated. When this happens all we have to do is call notifyObservers.
 Now lets create our Observer interface -

public interface Observer {
    
    public void update(Event event);

}


Notice observer interface has just one method -
  1. update - This method will be invoked on every registered observer by the corresponding subject

Finally lets create an Event interface  . This is just a interface with no methods in it. Each actual event like CricketEvent in our example will implement this interface. Other Events could be FinanceEvent, PoliticsEvent etc

public interface Event {

}

Very important point to note here - Why are we creating interfaces and not direct concrete implementation?

Remember the OO design principles mentioned in Introduction to Design Patterns 

  • Code for interface not implementation
And the reason is quite simple. If you code for concrete implementation then you have to change base code every time new entity is added.


Lets move on to our concrete classes implementations now.

First Lets write our CricketEvent -

public class CricketEvent implements Event {
    

    String team1;
    String team2;
    String matchLocation;
    String matchDate;

    

    public CricketEvent(String team1, String team2, String matchLocation, String matchDate) {
        this.team1 = team1;
        this.team2 = team2;
        this.matchLocation = matchLocation;
        this.matchDate = matchDate;
    }


    @Override
    public String toString() {
        return "CricketEvent [team1=" + team1 + ", team2=" + team2
                + ", matchLocation=" + matchLocation + ", matchDate="
                + matchDate + "]";
    }
    

}


Simple Cricket Event class with some attribute.

Next lets implement our Subject - CricketSubject.

public class CricketSubject implements Subject {

    

    List<Observer> registeredObservers;

    

    public CricketSubject() {
        registeredObservers = new ArrayList<>();
    }

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

    @Override
    public void deregisterObserver(Observer observer) {
        registeredObservers.remove(observer);
        
    }

    @Override
    public void notifyObservers(Event event) {
        for(Observer observer : registeredObservers) {
            observer.update(event);
        }
    }

   

    @Override
    public void onNewEvent(Event CricketEvent) {
        notifyObservers(CricketEvent);
    }

}


We are using a simple ArrayList to keep track of registered Observers. Whenever new Cricket is generated onNewCricketEvent method is called (you don't have to worry about this. All you have to know is whenever cricket event is generated this will be called.) then we call notifyObservers to notify all observers.

Lets now create class for CricketEventObserver -

public class CricketEventObserver implements Observer {
    
    public CricketEventObserver(Subject subject) {
        subject.registerObserver(this);
    }

    @Override
    public void update(Event event) {
        CricketEvent crickEvent = (CricketEvent) event;
        System.out.println("Received Cricket Event : " + crickEvent);
    }

}


Notice in constructor it takes an Observer reference and registers itself to it. Now lets simulate and see the working -

public class ObserverSimulation {

    public static void main(String args[]) {
       
        Subject cricketSubject = new CricketSubject();
        Observer cricketEventObserver1 = new CricketEventObserver(cricketSubject);
        Observer cricketEventObserver2 = new CricketEventObserver(cricketSubject);
       
        System.out.println("Generating Cricket Event");
        cricketSubject.onNewEvent(new CricketEvent("India", "Aus", "Melbourne Cricket Ground", "01/02/2015"));
        System.out.println("--------------------------");
        System.out.println("De registerting cricket observer 2");
        cricketSubject.deregisterObserver(cricketEventObserver2);
        System.out.println("--------------------------");
        System.out.println("Generating Cricket Event");
        cricketSubject.onNewEvent(new CricketEvent("India", "England", "Eden Gardens", "03/02/2015"));
        System.out.println("--------------------------");
    }
    
}



and the output is -

Generating Cricket Event
Received Cricket Event : CricketEvent [team1=India, team2=Aus, matchLocation=Melbourne Cricket Ground, matchDate=01/02/2015]
Received Cricket Event : CricketEvent [team1=India, team2=Aus, matchLocation=Melbourne Cricket Ground, matchDate=01/02/2015]
--------------------------
De registerting cricket observer 2
--------------------------
Generating Cricket Event
Received Cricket Event : CricketEvent [team1=India, team2=England, matchLocation=Eden Gardens, matchDate=03/02/2015]
--------------------------


as expected.

Class diagram for above Design is -




Java built in support for Observer pattern

Java provided built in support for Observer pattern with following two entities -
  1. class java.util.Observable
  2. interface java.util.Observer

Observable is a class and have methods like addObserver(), deleteObserver() etc where as Observer is an interface with method update() which Observable instance calls while notifying.

Note :
  • Before calling notifyObservers() you need to call setChanged() to mark the state changed. if you miss this notifyObservers() method will just return without notifying the observers.
  •  Also all methods in Observable class are synchronized which makes it's instances thread safe.

Observer pattern used in JDK

This pattern is used extensively in Swing.
javax.swing.AbstractButton class is the Subject and has concrete implementations like javax.swing.JButton. Observer is java.awt.event.ActionListener interface and you can create instances of it and register to JButton to receive Events update.

For example - 

    public static void main(String args[]) {

        JButton button = new JButton();
        button.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                System.out.println("Observer 1 : Action Event recived from JButton Subject");
                
            }
        });
        button.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                System.out.println("Observer 2 : Action Event recived from JButton Subject");
                
            }
        });
        
    }

Above code registers two concrete implementations of ActionListener interface with Subject JButton and whenever any action is triggered on the button these listeners will be notified.

Related Links



No comments:

Post a Comment

t> UA-39527780-1 back to top