SHARE
TWEET

Java Generic Observer

a guest Oct 31st, 2010 619 Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. /**
  2.  * A generic implementation of an Observable object as defined by the <a
  3.  * href="http://en.wikipedia.org/wiki/Observer_pattern">Observer pattern</a>.
  4.  * As a type parameter the interface for the Observer needs to be specified.
  5.  *
  6.  * @author Steven Jeuris
  7.  * @param <T>
  8.  *            The interface which should be implemented by the observers.
  9.  */
  10. public abstract class AbstractObservable<T> implements IAbstractObservable<T> {
  11.  
  12.     private T m_eventDispatcher = null;
  13.     /**
  14.      * The list of observers to which the event dispatcher forwards it calls.
  15.      */
  16.     private final ObserverPool<T> m_observers = new ObserverPool<T>();
  17.  
  18.     /**
  19.      * Get the event dispatcher through which you can notify the observers.
  20.      *
  21.      * @return The event dispatcher through which you can notify the observers.
  22.      */
  23.     protected T getEventDispatcher() {
  24.         // Only create one instance of the dispatcher.
  25.         if ( m_eventDispatcher == null ) {
  26.             // Use reflection to get the generic parameter type.
  27.             // Find the super class after 'AbstractObservable'.
  28.             Class<?> superClass = this.getClass();
  29.             while ( superClass.getSuperclass() != AbstractObservable.class ) {                  
  30.                 superClass = superClass.getSuperclass();
  31.             }            
  32.            
  33.             // Get the generic class for AbstractObservable, so that parameter types
  34.             // can be extracted.
  35.             Type genericClass = superClass.getGenericSuperclass();
  36.             if ( genericClass instanceof Class<?> ) {                
  37.                 new RuntimeException( "Observable requires a parameter type!" );
  38.             }
  39.             else {
  40.                 // Get the parameter type.
  41.                 ParameterizedType genericType = (ParameterizedType)genericClass;                
  42.                 Type[] typeArguments = genericType.getActualTypeArguments();
  43.  
  44.                 m_eventDispatcher = m_observers.createEventDispatcher( (Class<?>)typeArguments[0] );
  45.             }
  46.  
  47.         }
  48.  
  49.         return m_eventDispatcher;
  50.     }
  51.  
  52.     /*
  53.      * (non-Javadoc)
  54.      *
  55.      * @see be.hyp3.patterns.observer.IObservable#addObserver(T)
  56.      */
  57.     public void addObserver( T observer ) {
  58.         m_observers.addObserver( observer );
  59.     }
  60.  
  61.     /*
  62.      * (non-Javadoc)
  63.      *
  64.      * @see be.hyp3.patterns.observer.IObservable#removeObserver(T)
  65.      */
  66.     public boolean removeObserver( T observer ) {
  67.         return m_observers.removeObserver( observer );
  68.     }
  69.  
  70. }
  71.  
  72. /**
  73.  * The ObserverPool is a proxy which allows calls to an interface to be forwarded to a set of listeners.
  74.  *
  75.  * @author Steven Jeuris
  76.  *
  77.  * @param <T>
  78.  *            The interface which defines which calls can be made to the listeners.
  79.  */
  80. class ObserverPool<T> implements InvocationHandler {
  81.  
  82.     /**
  83.      * The list of listeners. Additions and removals greatly outnumber traversals,
  84.      * so a CopyOnWriteArrayList is the most efficient solution.
  85.      */
  86.     private List<T> m_pool = new CopyOnWriteArrayList<T>();
  87.  
  88.     /**
  89.      * Add an observer to which the calls will be made.
  90.      *
  91.      * @param observer
  92.      *            The observer to add.
  93.      */
  94.     public void addObserver( T observer ) {
  95.         m_pool.add( observer );
  96.     }
  97.  
  98.     /**
  99.      * Remove an observer to which calls where being made.
  100.      *
  101.      * @param observer
  102.      *            The observer to remove.
  103.      *
  104.      * @return True, when the observer was found and removed, false otherwise.
  105.      */
  106.     public boolean removeObserver( T observer ) {
  107.         return m_pool.remove( observer );
  108.     }
  109.  
  110.     /**
  111.      * Create the proxy which allows to dispatch all calls to the observers.
  112.      *
  113.      * @param observerClass
  114.      *            The interface class of the observers.
  115.      *
  116.      * @return The dispatcher which can be used to make calls to all added observers.
  117.      */
  118.     @SuppressWarnings( "unchecked" )
  119.     public T createEventDispatcher( Class observerClass ) {
  120.         T dispatcher = (T)Proxy.newProxyInstance(
  121.             observerClass.getClassLoader(),
  122.             new Class[] { observerClass },
  123.             this );
  124.  
  125.         return dispatcher;
  126.     }
  127.  
  128.     /**
  129.      * invoke() implementation of InvocationHandler.
  130.      * This is called whenever a call is made to an event dispatcher.
  131.      */
  132.     @Override
  133.     public Object invoke( Object object, Method method, Object[] args ) throws Throwable {
  134.         // Forward the call to all observers.
  135.         for ( T observer : m_pool ) {
  136.             method.invoke( observer, args );
  137.         }
  138.  
  139.         // No return object available.
  140.         return null;
  141.     }
  142.  
  143. }
  144.  
  145. /**
  146.  * An interface to the abstract Observable class.
  147.  *
  148.  * @author Steven Jeuris
  149.  * @param <T>
  150.  */
  151. public interface IAbstractObservable<T> {
  152.  
  153.     /**
  154.      * Add an observer which will listen to the actions of this object.
  155.      *
  156.      * @param observer
  157.      *            The observer which should listen to this observable.
  158.      */
  159.     public abstract void addObserver( T observer );
  160.  
  161.     /**
  162.      * Remove an observer which was listening to this object.
  163.      *
  164.      * @param observer
  165.      *            The observer to remove.
  166.      *
  167.      * @return True, when observer was found and removed, false otherwise.
  168.      */
  169.     public abstract boolean removeObserver( T observer );
  170.  
  171. }
RAW Paste Data
Top