Sunday, December 9, 2012

Design Patterns : Observer Pattern 1

These days I have been learning design patterns. Since Singleton and Factory are already done to death with, I decided to choose a somewhat obscure one. Observer pattern.

Let's say we have a bean User which implements the below interface


package org.home.project21.study.designPatterns;

/**
 *
 *
 * @author Sanjay
 *
 */
public interface IUser {


    /**
     *
     *
     * @return
     */
    public String getUserName();
}
 
and which is intended to log a user into an interface like something below

package org.home.project21.study.designPatterns;

/**
 *
 *
 * @author Sanjay
 *
 */
public interface ILogUser {

    /**
     *
     *
     *
     * @param userName
     * @param password
     * @return
     */
    public IUser login(String userName, char [] password);
   
    /**
     *
     *
     *
     *
     * @param userName
     * @param password
     * @return
     */
    public IUser logout(String userName, char [] password);
   
    /**
     *
     *
     *
     * @return
     */
    public boolean isLogged(IUser user);
}
 



Now we would like to keep an eye on who logs on to the System. So we decide to create an observable system. Fortunately for us Java has already created a class 
  Observable which can be used for the purpose. For clarity we would extend it. Next we need an Observer class which will intimate us when it notices something 'Observable'. 


package org.home.project21.study.designPatterns;

import java.util.Calendar;
import java.util.Observable;
import java.util.Observer;

/**
 *
 * This class implements the Observer
 *
 * @author Sanjay
 *
 */
public class LoginObserver implements Observer {

    /**
     *
     *
     */
    @Override
    public void update(Observable arg0, Object arg1) {
        // TODO Auto-generated method stub
        ILogUser loginObservable = (ILogUser) arg0;
        IUser user = (IUser) arg1;
        System.out.println(" Observer notes " + user + " has " + (loginObservable.isLogged(user)?" logged In ":" logged Out ")
                + " @ " + Calendar.getInstance().getTime() + " " + Calendar.getInstance().getTimeZone());
    }

}




The observer class will update the System whenever the update method is invoked.

Now let us turn our attention to the main class The actual Observable. Since it is relatively bigger we would take it chunk by chunk. For completeness below is the source code


package org.home.project21.study.designPatterns;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Observable;
import java.util.Observer;

/**
 *
 * This class extends the Observable Class
 *
 * @author Sanjay
 *
 */
public class LoginObservable extends Observable implements ILogUser  {
   
    private List observers;
    private Map currentUsers_;
   
    private boolean changed;
   
    public boolean isLogged(IUser user) {
        if(currentUsers_ != null && currentUsers_.containsKey(user.getUserName())) return true;
        else return false;
    }


   
    /**
     *
     *
     *
     */
    public IUser login(String userName, char [] password) {
        // check pss
        changed = true;
        IUser user = new User(userName);
        if(currentUsers_ == null) {
            currentUsers_ = new HashMap();
        }
        currentUsers_.put(userName, user);
        notifyObservers(user);// notify all Observers of this user
        return user;
    }
   
    /**
     *
     *
     *
     *
     */
    public IUser logout(String userName, char [] password) {
        // check pss
        changed = true;
        IUser user = null;
        if(currentUsers_ != null) {
            if(currentUsers_.containsKey(userName)) {
                //double check pss
                user = currentUsers_.get(userName);
                currentUsers_.put(userName, null);
            }
        }
        notifyObservers(user);// notify all Observers of this user
        return user;
    }
   


    /**
     *
     *
     *
     */
    public LoginObservable() {
        // TODO Auto-generated constructor stub
        super();
        observers = new ArrayList();
        changed = false;
    }
   
   
    @Override
    public synchronized void addObserver(Observer o) {
        // TODO Auto-generated method stub
        if(observers != null) {
            observers.add(o);
        }
        else {
            throw new NullPointerException("observers == " + observers);
        }
    }
   
    @Override
    public synchronized int countObservers() {
        // TODO Auto-generated method stub
        if(observers != null) {
            return observers.size();
        }
        else {
            throw new NullPointerException("observers == " + observers);
        }
    }
   
    @Override
    public synchronized void deleteObserver(Observer o) {
        // TODO Auto-generated method stub
        if(observers != null) {
            if(observers.contains(o)) {
                observers.set(observers.indexOf(o), null);
            }
            else {
                throw new IllegalArgumentException( o + " not found in " + observers);
            }
        }
        else {
            throw new NullPointerException("observers == " + observers);
        }
    }
   
    @Override
    public synchronized void deleteObservers() {
        // TODO Auto-generated method stub
        if(observers != null) {
            observers = null;
           
        }       
        observers = new ArrayList();
    }
   
    @Override
    public boolean equals(Object obj) {
        // TODO Auto-generated method stub
        if(obj instanceof LoginObservable) {
            if(((LoginObservable)obj).observers != null && this.observers != null) {
                return this.observers.equals(((LoginObservable)obj).observers);
            }
            else {
                return false;
            }
        }
        return false;
    }
   
    @Override
    public synchronized boolean hasChanged() {
        // TODO Auto-generated method stub
        return changed;
    }
   
    @Override
    public void notifyObservers() {
        // TODO Auto-generated method stub
        this.notifyObservers(null);
    }
   
    @Override
    public void notifyObservers(Object arg) {
        // TODO Auto-generated method stub
        Observer [] observersArray =  new Observer[observers.size()];
        int count = 0;
        for(Observer observer : observers) {
            observersArray[count++] = observer;
        }
       
        if(this.hasChanged()) {
            for(Observer observer : observersArray) {
                observer.update(this, arg);
            }
        }
        clearChanged();
        observersArray = null;
    }
   
    @Override
    public String toString() {
        // TODO Auto-generated method stub
        return " observers " + this.observers.toString();
    }
   
    @Override
    protected synchronized void clearChanged() {
        // TODO Auto-generated method stub
        changed = false;
    }
}
 




No comments:

Post a Comment