zoukankan      html  css  js  c++  java
  • Java内置Observerable类的源码分析

    package java.util;
    /** * This class represents an observable object, or "data" 
    	* in the model-view paradigm. It can be subclassed to represent an 	
    	* object that the 	application wants to have observed. 
    	* <p> 
    	* An observable object can have one or more observers. An observer 
    	* may be any object that implements interface <tt>Observer</tt>. After an 
    	* observable instance changes, an application calling the 
    	* <code>Observable</code>'s <code>notifyObservers</code> method 
    	* causes all of its observers to be notified of the change by a call 
    	* to their <code>update</code> method. 
    	* <p> 
    	* The order in which notifications will be delivered is unspecified. 
    	* The default implementation provided in the Observable class will 
    	* notify Observers in the order in which they registered interest, but 
    	* subclasses may change this order, use no guaranteed order, deliver 
    	* notifications on separate threads, or may guarantee that their 
    	* subclass follows this order, as they choose. 
    	* <p> 
    	* Note that this notification mechanism has nothing to do with threads 
    	* and is completely separate from the <tt>wait</tt> and <tt>notify</tt> 
    	* mechanism of class <tt>Object</tt>. 
    	* <p> 
    	* When an observable object is newly created, its set of observers is 
    	* empty. Two observers are considered the same if and only if the 
    	* <tt>equals</tt> method returns true for them. 
    	* 
    	* @author  Chris Warth 
    	* @see     java.util.Observable#notifyObservers() 
    	* @see     java.util.Observable#notifyObservers(java.lang.Object) 
    	* @see     java.util.Observer 
    	* @see     java.util.Observer#update(java.util.Observable, java.lang.Object) 
    	* @since   JDK1.0 
    	*/public class Observable {    
    	private boolean changed = false;    
    	private Vector<Observer> obs;    
    	/** Construct an Observable with zero Observers. */    
    	public Observable() {        
    		obs = new Vector<>();    
        }    
        /**     
          * Adds an observer to the set of observers for this object, provided     
          * that it is not the same as some observer already in the set.     
          * The order in which notifications will be delivered to multiple     
          * observers is not specified. See the class comment.     
          *     
          * @param   o   an observer to be added.     
          * @throws NullPointerException   if the parameter o is null.     
          */    
          public synchronized void addObserver(Observer o) {        
          if (o == null)            
          throw new NullPointerException();        
          	if (!obs.contains(o)) {            
          	obs.addElement(o);        
          	}    
          }    
          /**     
            * Deletes an observer from the set of observers of this object.     
            * Passing <CODE>null</CODE> to this method will have no effect.     
            * @param   o   the observer to be deleted.     
            */    
            public synchronized void deleteObserver(Observer o) {
            	obs.removeElement(o);    
            }    
            /**     
            * If this object has changed, as indicated by the     
            * <code>hasChanged</code> method, then notify all of its observers     
            * and then call the <code>clearChanged</code> method to     
            * indicate that this object has no longer changed.     
            * <p>     
            * Each observer has its <code>update</code> method called with two     
            * arguments: this observable object and <code>null</code>. In other     
            * words, this method is equivalent to:     
            * <blockquote><tt>     
            * notifyObservers(null)</tt></blockquote>     
            *     
            * @see     java.util.Observable#clearChanged()     
            * @see     java.util.Observable#hasChanged()     
            * @see     java.util.Observer#update(java.util.Observable, java.lang.Object)     		 */    
            public void notifyObservers() {        
            	notifyObservers(null);    
            }    
            /**     
              * If this object has changed, as indicated by the     
              * <code>hasChanged</code> method, then notify all of its observers     
              * and then call the <code>clearChanged</code> method to indicate     
              * that this object has no longer changed.     
              * <p>     
              * Each observer has its <code>update</code> method called with two     
              * arguments: this observable object and the <code>arg</code> argument.     
              *     
              * @param   arg   any object.     
              * @see     java.util.Observable#clearChanged()     
              * @see     java.util.Observable#hasChanged()     
              * @see     java.util.Observer#update(java.util.Observable, java.lang.Object)     			*/    
              public void notifyObservers(Object arg) {        
              /*         
               * a temporary array buffer, used as a snapshot of the state of         
               * current Observers.         
               */        
               		Object[] arrLocal;        
               		synchronized (this) {            
               			/* We don't want the Observer doing callbacks into             
               			* arbitrary code while holding its own Monitor.             
               			* The code where we extract each Observable from             
               			* the Vector and store the state of the Observer             
               			* needs synchronization, but notifying observers             
               			* does not (should not).  The worst result of any             
               			* potential race-condition here is that:             
               			* 1) a newly-added Observer will miss a             
               			*   notification in progress             
               			* 2) a recently unregistered Observer will be             
               			*   wrongly notified when it doesn't care             
               			*/            
               			if (!changed)                
               				return;            
               			arrLocal = obs.toArray();            
               			clearChanged();        
               		}        
               		for (int i = arrLocal.length-1; i>=0; i--){
                    	((Observer)arrLocal[i]).update(this, arg);    
                    }    
                    /**     
                      * Clears the observer list so that this object no longer has any 
                      * observers.     
                      */    
              public synchronized void deleteObservers() {        
              		obs.removeAllElements();    
              }    
              /**     
                * Marks this <tt>Observable</tt> object as having been changed; the     
                * <tt>hasChanged</tt> method will now return <tt>true</tt>.     
                */    
              protected synchronized void setChanged() {        
              		changed = true;    
              }    
              /**     
                * Indicates that this object has no longer changed, or that it has     
                * already notified all of its observers of its most recent change,     
                * so that the <tt>hasChanged</tt> method will now return <tt>false</tt>.     			 * This method is called automatically by the     
                * <code>notifyObservers</code> methods.     
                *     
                * @see     java.util.Observable#notifyObservers()     
                * @see     java.util.Observable#notifyObservers(java.lang.Object)     
                */    
              protected synchronized void clearChanged() {        
              		changed = false;    
              }    
              /**     
                * Tests if this object has changed.     
                *     
                * @return  <code>true</code> if and only if the <code>setChanged</code>     
                *          method has been called more recently than the     
                *          <code>clearChanged</code> method on this object;     
                *          <code>false</code> otherwise.     
                * @see     java.util.Observable#clearChanged()     
                * @see     java.util.Observable#setChanged()     
                */    
             public synchronized boolean hasChanged() {        
             		return changed;    
             }    
             /**     
               * Returns the number of observers of this <tt>Observable</tt> object.     
               *     
               * @return  the number of observers of this object.     
               */    
             public synchronized int countObservers() {        
             		return obs.size();    
             }
          }
    

    源码简析:

    1. 此类中使用vector集合,这个集合应该是被废弃的,因为这个集合是一个多线程安全的集合,为了线程安全,使用了时间换空间的策略,所以时间很慢,再加上对元素的增删速度慢,成为弃婴。

    2. vector的优点:

      • 线程同步

      • 数组是数组长度可变(当数组动态扩容需要消耗不少时间,影响性能)

      • 特有的方法:

        ​ void addElement(E obj) 在集合末尾添加元素

        ​ E elementAt( int index) 返回指定角标的元素

        ​ Enumeration elements() 返回集合中的所有元素,封装到Enumeration对象中测试此枚举是否包含更多的元素。

        ​ E nextElement() 如果此枚举对象至少还有一个可提供的元素,则返回此枚举的下一个元素。

        ​ Enumeration 接口: boolean hasMoreElements()

    3. 此类中添加了一个changed的布尔标识,用来发现被观察者的信息是否变化

    4. 在注册/移除观察者时,添加了synchronized锁,防止其他线程执行里面的代码造成数据不安全

    5. 改变类变量的方法好像他都锁了一下

    6. 在执行notifyObserver(object o)方法时,判断了一下changed,false就直接返回,不做更新操作;true的话就将changed重置为false,然后将更新的信息发给每一个观察者

    java内置的Observerable的缺点

    1. 它使用的是类定义而不是接口定义,这样会使得这个类减少复用机会,而且不容易扩展

    2. 它违背了“设计应该多使用组合,少使用继承”的设计原则,比如在方法中添加了protest关键字,使得只用继承此类的类才能使用此方法。

      除了util包外,在swings包和javabeans包也体现了observer模式。其实mvc模式也是观察者模式的代表。

    ​ em...... 大致就这些东西.

  • 相关阅读:
    15. DML, DDL, LOGON 触发器
    5. 跟踪标记 (Trace Flag) 834, 845 对内存页行为的影响
    4. 跟踪标记 (Trace Flag) 610 对索引组织表(IOT)最小化日志
    14. 类似正则表达式的字符处理问题
    01. SELECT显示和PRINT打印超长的字符
    3. 跟踪标记 (Trace Flag) 1204, 1222 抓取死锁信息
    2. 跟踪标记 (Trace Flag) 3604, 3605 输出DBCC命令结果
    1. 跟踪标记 (Trace Flag) 1117, 1118 文件增长及空间分配方式
    0. 跟踪标记 (Trace Flag) 简介
    SpringBoot + Redis + Shiro 实现权限管理(转)
  • 原文地址:https://www.cnblogs.com/glassysky/p/12490369.html
Copyright © 2011-2022 走看看