Guest User

Java Generic Observer

a guest
Oct 31st, 2010
847
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

Adblocker detected! Please consider disabling it...

We've detected AdBlock Plus or some other adblocking software preventing Pastebin.com from fully loading.

We don't have any obnoxious sound, or popup ads, we actively block these annoying types of ads!

Please add Pastebin.com to your ad blocker whitelist or disable your adblocking software.

×