JAVA观察者模式(蚊子咬我)

 
                                                 设计模式之观察者模式
     前两天在下大雨,蚊子 也开始兴师动众都向我们寝室的蚊帐进军,我也成了被害人之一,被一个个蚊子攻击的滋味不好受 于是晚上半夜三点起来打蚊子 就睡不着了,想象该死的蚊子 如果 你咬我我就打你该多好 "血债血还" 你吃我的血我就把你打成血团子,下面就来写写这样一个模拟代码
  
   观察者模式 用于比较多的是JAVA GUI编程里面,下面下面介绍几个接口和类EventObject ,EventListener,EventListenerList
下面看看源代码:
/*
* @(#)EventObject.java  1.21 05/11/17
*
* Copyright 2006 Sun Microsystems, Inc. All rights reserved.
* SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
*/

package java.util;

/**
* <p>
* The root class from which all event state objects shall be derived.
* <p>
* All Events are constructed with a reference to the object, the "source",
* that is logically deemed to be the object upon which the Event in question
* initially occurred upon.
*    
* @since JDK1.1
*/

public class EventObject implements java.io.Serializable {

         private static final long serialVersionUID = 5516075349620653480L;

         /**
         * The object on which the Event initially occurred.
         */
         protected transient Object    source;

         /**
         * Constructs a prototypical Event.
         *
         * @param        source        The object on which the Event initially occurred.
         * @exception    IllegalArgumentException    if source is null.
         */
         public EventObject(Object source) {
   if (source == null)
         throw new IllegalArgumentException( "null source");

                 this.source = source;
        }

         /**
         * The object on which the Event initially occurred.
         *
         * @return     The object on which the Event initially occurred.
         */
         public Object getSource() {
                 return source;
        }

         /**
         * Returns a String representation of this EventObject.
         *
         * @return    A a String representation of this EventObject.
         */
         public String toString() {
                 return getClass().getName() + "[source=" + source + "]";
        }
}
事件对象包含了对象源
EventListenner
/*
* @(#)EventListener.java  1.14 05/11/17
*
* Copyright 2006 Sun Microsystems, Inc. All rights reserved.
* SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
*/

package java.util;

/**
* A tagging interface that all event listener interfaces must extend.
* @since JDK1.1
*/
public interface EventListener {
}
EventListenerList
/*
* @(#)EventListenerList.java  1.37 05/11/17
*
* Copyright 2006 Sun Microsystems, Inc. All rights reserved.
* SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
*/
package javax.swing.event;

import java.io.*;
import java.util.*;
import java.lang.reflect.Array;    

/**
* A class that holds a list of EventListeners.    A single instance
* can be used to hold all listeners (of all types) for the instance
* using the list.    It is the responsiblity of the class using the
* EventListenerList to provide type-safe API (preferably conforming
* to the JavaBeans spec) and methods which dispatch event notification
* methods to appropriate Event Listeners on the list.
*    
* The main benefits that this class provides are that it is relatively
* cheap in the case of no listeners, and it provides serialization for    
* event-listener lists in a single place, as well as a degree of MT safety
* (when used correctly).
*
* Usage example:
*        Say one is defining a class that sends out FooEvents, and one wants
* to allow users of the class to register FooListeners and receive    
* notification when FooEvents occur.    The following should be added
* to the class definition:
* <pre>
* EventListenerList listenerList = new EventListenerList();
* FooEvent fooEvent = null;
*
* public void addFooListener(FooListener l) {
*         listenerList.add(FooListener.class, l);
* }
*
* public void removeFooListener(FooListener l) {
*         listenerList.remove(FooListener.class, l);
* }
*
*
* // Notify all listeners that have registered interest for
* // notification on this event type.    The event instance    
* // is lazily created using the parameters passed into    
* // the fire method.
*
* protected void fireFooXXX() {
*         // Guaranteed to return a non-null array
*         Object[] listeners = listenerList.getListenerList();
*         // Process the listeners last to first, notifying
*         // those that are interested in this event
*         for (int i = listeners.length-2; i>=0; i-=2) {
*                 if (listeners[i]==FooListener.class) {
*                         // Lazily create the event:
*                         if (fooEvent == null)
*                                 fooEvent = new FooEvent(this);
*                         ((FooListener)listeners[i+1]).fooXXX(fooEvent);
*                 }
*         }
* }
* </pre>
* foo should be changed to the appropriate name, and fireFooXxx to the
* appropriate method name.    One fire method should exist for each
* notification method in the FooListener interface.
* <p>
* <strong>Warning:</strong>
* Serialized objects of this class will not be compatible with
* future Swing releases. The current serialization support is
* appropriate for short term storage or RMI between applications running
* the same version of Swing.    As of 1.4, support for long term storage
* of all JavaBeans<sup><font size="-2">TM</font></sup>
* has been added to the <code>java.beans</code> package.
* Please see {@link java.beans.XMLEncoder}.
*
* @version 1.37 11/17/05
* @author Georges Saab
* @author Hans Muller
* @author James Gosling
*/
public class EventListenerList implements Serializable {
         /* A null array to be shared by all empty listener lists*/
         private final static Object[] NULL_ARRAY = new Object[0];
         /* The list of ListenerType - Listener pairs */
         protected transient Object[] listenerList = NULL_ARRAY;

         /**
         * Passes back the event listener list as an array
         * of ListenerType-listener pairs.    Note that for    
         * performance reasons, this implementation passes back    
         * the actual data structure in which the listener data
         * is stored internally!    
         * This method is guaranteed to pass back a non-null
         * array, so that no null-checking is required in    
         * fire methods.    A zero-length array of Object should
         * be returned if there are currently no listeners.
         *    
         * WARNING!!! Absolutely NO modification of
         * the data contained in this array should be made -- if
         * any such manipulation is necessary, it should be done
         * on a copy of the array returned rather than the array    
         * itself.
         */
         public Object[] getListenerList() {
   return listenerList;
        }

         /**
         * Return an array of all the listeners of the given type.    
         * @return all of the listeners of the specified type.    
         * @exception    ClassCastException if the supplied class
         *    is not assignable to EventListener
         *    
         * @since 1.3
         */
         public <T extends EventListener> T[] getListeners(Class<T> t) {
  Object[] lList = listenerList;    
   int n = getListenerCount(lList, t);    
                T[] result = (T[])Array.newInstance(t, n);    
   int j = 0;    
   for ( int i = lList.length-2; i>=0; i-=2) {
         if (lList[i] == t) {
    result[j++] = (T)lList[i+1];
         }
  }
   return result;        
        }

         /**
         * Returns the total number of listeners for this listener list.
         */
         public int getListenerCount() {
   return listenerList.length/2;
        }

         /**
         * Returns the total number of listeners of the supplied type    
         * for this listener list.
         */
         public int getListenerCount(Class<?> t) {
  Object[] lList = listenerList;
                 return getListenerCount(lList, t);
        }

         private int getListenerCount(Object[] list, Class t) {
                 int count = 0;
   for ( int i = 0; i < list.length; i+=2) {
         if (t == (Class)list[i])
    count++;
  }
   return count;
        }

         /**
         * Adds the listener as a listener of the specified type.
         * @param t the type of the listener to be added
         * @param l the listener to be added
         */
         public synchronized <T extends EventListener> void add(Class<T> t, T l) {
   if (l== null) {
         // In an ideal world, we would do an assertion here
         // to help developers know they are probably doing
         // something wrong
         return;
  }
   if (!t.isInstance(l)) {
         throw new IllegalArgumentException( "Listener " + l +
             " is not of type " + t);
  }
   if (listenerList == NULL_ARRAY) {
         // if this is the first listener added,    
         // initialize the lists
         listenerList = new Object[] { t, l };
  } else {
         // Otherwise copy the array and add the new listener
         int i = listenerList.length;
         Object[] tmp = new Object[i+2];
         System.arraycopy(listenerList, 0, tmp, 0, i);

         tmp[i] = t;
         tmp[i+1] = l;

         listenerList = tmp;
  }
        }

         /**
         * Removes the listener as a listener of the specified type.
         * @param t the type of the listener to be removed
         * @param l the listener to be removed
         */
         public synchronized <T extends EventListener> void remove(Class<T> t, T l) {
   if (l == null) {
         // In an ideal world, we would do an assertion here
         // to help developers know they are probably doing
         // something wrong
         return;
  }
   if (!t.isInstance(l)) {
         throw new IllegalArgumentException( "Listener " + l +
             " is not of type " + t);
  }
   // Is l on the list?
   int index = -1;
   for ( int i = listenerList.length-2; i>=0; i-=2) {
         if ((listenerList[i]==t) && (listenerList[i+1].equals(l) == true)) {
    index = i;
     break;
         }
  }
    
   // If so,    remove it
   if (index != -1) {
         Object[] tmp = new Object[listenerList.length-2];
         // Copy the list up to index
         System.arraycopy(listenerList, 0, tmp, 0, index);
         // Copy from two past the index, up to
         // the end of tmp (which is two elements
         // shorter than the old list)
         if (index < tmp.length)
    System.arraycopy(listenerList, index+2, tmp, index,    
         tmp.length - index);
         // set the listener array to the new array or null
         listenerList = (tmp.length == 0) ? NULL_ARRAY : tmp;
         }
        }

         // Serialization support.    
         private void writeObject(ObjectOutputStream s) throws IOException {
  Object[] lList = listenerList;
  s.defaultWriteObject();
    
   // Save the non-null event listeners:
   for ( int i = 0; i < lList.length; i+=2) {
         Class t = (Class)lList[i];
         EventListener l = (EventListener)lList[i+1];
         if ((l!= null) && (l instanceof Serializable)) {
    s.writeObject(t.getName());
    s.writeObject(l);
         }
  }
    
  s.writeObject( null);
        }

         private void readObject(ObjectInputStream s)    
   throws IOException, ClassNotFoundException {
                listenerList = NULL_ARRAY;
  s.defaultReadObject();
  Object listenerTypeOrNull;
    
   while ( null != (listenerTypeOrNull = s.readObject())) {
                        ClassLoader cl = Thread.currentThread().getContextClassLoader();
         EventListener l = (EventListener)s.readObject();
         add((Class<EventListener>)Class.forName((String)listenerTypeOrNull, true, cl), l);
  }            
        }

         /**
         * Returns a string representation of the EventListenerList.
         */
         public String toString() {
  Object[] lList = listenerList;
  String s = "EventListenerList: ";
  s += lList.length/2 + " listeners: ";
   for ( int i = 0 ; i <= lList.length-2 ; i+=2) {
         s += " type " + ((Class)lList[i]).getName();
         s += " listener " + lList[i+1];
  }
   return s;
        }
}
看看源代码就很清楚了 ,下面开始介绍我们的蚊子大战
定义一个事件类
package MosquitoBiteMe;
/**
* 定义 咬人事件    
*/
import java.util.Date;
import java.util.EventObject;
/**
* 四川师范大学 06级    
* @author Administrator
*
*/
@SuppressWarnings(value={ "unchecked", "serial"})
public class BiteEvent extends EventObject{
/**
    * 事件发生事件
    */
     private Date date; //时间发生时间
     /**
     * 调用父类构造方法 传入 源和事件
     * @param obj
     * @param d
     */
     public BiteEvent(Object obj,Date d){
     super(obj);
     this.date=d;
    }
   public Date getDate() {
     return date;
  }
}
定义事件
/*
* 蚊子 要人的 监听器
*/
package MosquitoBiteMe;
import java.util.EventListener;
/*
* 四川师范大学 06级 刘毅
*/
public     interface BiteListener extends EventListener {
     public void biteAction(BiteEvent event);
}

定义蚊子
package MosquitoBiteMe;
/*
* 蚊子类
*/
import java.util.Date;

import javax.swing.event.EventListenerList;
/*
* 四川师范大学 06级 刘毅
*/
@SuppressWarnings(value={ "unchecked"})
public class Mosquito{
   /**
    * 记录对该对象所添加的监听器
    */
         private EventListenerList listenerlist= new EventListenerList();
   /**
    * 添加一个BL 监听器 到 蚊子上
    * @param bl
    */
         public void    addBiteListener(BiteListener bl){
          listenerlist.add(BiteListener. class, bl);
        }
             /**
         * 咬人
         */
         public void bite(){
          BiteEvent be= new BiteEvent( this, new Date());
          Object bls[]=listenerlist.getListeners(BiteListener. class);    
           for(Object bl:bls){
             /**
             * 通知监听器 执行监听代码
             */
            ((BiteListener)bl).biteAction(be);
          }
        }
}
测试类:
package MosquitoBiteMe;

public class Test {

   /**
    * @param args
    */
   public static void main(String[] args) {
     // TODO Auto-generated method stub
                    Mosquito mo = new Mosquito();
                    mo.addBiteListener( new BiteListener(){
       public void biteAction(BiteEvent event) {
         // TODO Auto-generated method stub
        System.out.print( "蚊子:\""+event.getSource().hashCode()+ "\" 于 "+event.getDate()+ " 咬了我!!");
             System.out.println( " 打死你...");
      }
                    });
                    mo.addBiteListener( new BiteListener(){
           public void biteAction(BiteEvent event) {
             // TODO Auto-generated method stub
            System.out.println( "蚊子:\""+event.getSource().hashCode()+ "\" 于 "+event.getDate()+ " 咬了我!!");
          }
                        });
                    mo.bite();
  }

}
我在一个蚊子上添加了两个监听器: 一个好人 ,一个有仇必报的人
当蚊子咬人的时候执行结果为
蚊子: "827574" 于 Fri Aug 28 10:23:23 CST 2009 咬了我!!
蚊子: "827574" 于 Fri Aug 28 10:23:23 CST 2009 咬了我!! 打死你...
OK 完了
相信 应该很理解 观察者模式了
 

你可能感兴趣的:(java,设计模式,职场,观察者,休闲)