zoukankan      html  css  js  c++  java
  • Java_观察者模式(Observable和Observer)

    http://blog.csdn.net/tianjf0514/article/details/7475164/

    一、观察者模式介绍

    在Java中通过Observable类和Observer接口实现了观察者模式。一个Observer对象监视着一个Observable对象的变化,当Observable对象发生变化时,Observer得到通知,就可以进行相应的工作。

    如果画面A是显示数据库里面的数据,而画面B修改了数据库里面的数据,那么这时候画面A就要重新Load。这时候就可以用到观察者模式

    二、观察者模式实现方法

    java.util.Observable中有两个方法对Observer特别重要

    ①setChanged()方法

    [java] view plain copy
    1. /** 
    2.  * Sets the changed flag for this {@code Observable}. After calling 
    3.  * {@code setChanged()}, {@code hasChanged()} will return {@code true}. 
    4.  */  
    5. protected void setChanged() {  
    6.     changed = true;  
    7. }  
    ②notifyObservers()方法 / notifyObservers(Object data)方法
    [java] view plain copy
    1. /** 
    2.  * If {@code hasChanged()} returns {@code true}, calls the {@code update()} 
    3.  * method for every observer in the list of observers using null as the 
    4.  * argument. Afterwards, calls {@code clearChanged()}. 
    5.  * <p> 
    6.  * Equivalent to calling {@code notifyObservers(null)}. 
    7.  */  
    8. public void notifyObservers() {  
    9.     notifyObservers(null);  
    10. }  
    11.   
    12. /** 
    13.  * If {@code hasChanged()} returns {@code true}, calls the {@code update()} 
    14.  * method for every Observer in the list of observers using the specified 
    15.  * argument. Afterwards calls {@code clearChanged()}. 
    16.  * 
    17.  * @param data 
    18.  *            the argument passed to {@code update()}. 
    19.  */  
    20. @SuppressWarnings("unchecked")  
    21. public void notifyObservers(Object data) {  
    22.     int size = 0;  
    23.     Observer[] arrays = null;  
    24.     synchronized (this) {  
    25.         if (hasChanged()) {  
    26.             clearChanged();  
    27.             size = observers.size();  
    28.             arrays = new Observer[size];  
    29.             observers.toArray(arrays);  
    30.         }  
    31.     }  
    32.     if (arrays != null) {  
    33.         for (Observer observer : arrays) {  
    34.             observer.update(this, data);  
    35.         }  
    36.     }  
    37. }  

    以上两个方法十分重要

    setChanged()方法 —— 

    用来设置一个内部标志位注明数据发生了变化

    notifyObservers()方法 / notifyObservers(Object data)方法 —— 

    通知所有的Observer数据发生了变化,这时所有的Observer会自动调用复写好的update(Observable observable, Object data)方法来做一些处理(比如说画面数据的更新)。

    我们可以看到通知Observer有两个方法,一个无参,一个有参。那么这个参数有什么作用呢?

    其中一个作用:现在我不想通知所有的Observer,而只想其中一个指定的Observer做一些处理,那么就可以传一个参数作为ID,然后在所有的Observer中判断,每个Observer判断只有接收到底参数ID是属于自己的才做一些处理。

    当然参数还有其他作用,我只是举了个例子。

    下面举个例子加以说明:

    [java] view plain copy
    1. import java.util.Observable;    
    2. /** 
    3.  * 被观察者类 
    4.  */      
    5. public class SimpleObservable extends Observable    
    6. {    
    7.    private int data = 0;    
    8.       
    9.    public int getData(){     
    10.        return data;    
    11.    }    
    12.       
    13.    public void setData(int i){    
    14.        if(this.data != i) {   
    15.           this.data = i;   
    16.           setChanged();    
    17.   
    18.           //只有在setChange()被调用后,notifyObservers()才会去调用update(),否则什么都不干。  
    19.           notifyObservers();      
    20.        }    
    21.    }    
    22. }    

    上面这个类是一个被观察者类,它继承了Observable类,表示这个类是可以被观察的。

    然后在setData()方法里面,也就是数据改变的地方,来调用Observable类的setChanged()方法和notifyObservers()方法,表示数据已改变并通知所有的Observer调用它们的update()方法做一些处理。

    注意:只有在setChange()被调用后,notifyObservers()才会去调用update(),否则什么都不干。

    [java] view plain copy
    1. /** 
    2.  * 观察者类 
    3.  */        
    4. public class SimpleObserver implements Observer    
    5. {    
    6.    public SimpleObserver(SimpleObservable simpleObservable){    
    7.       simpleObservable.addObserver(this );    
    8.    }    
    9.       
    10.    public void update(Observable observable ,Object data){  // data为任意对象,用于传递参数  
    11.       System.out.println(“Data has changed to” + (SimpleObservable)observable.getData());    
    12.    }    
    13. }   


     

    通过生成被观察者(SimpleObservable类)的实例,来调用addObserver(this)方法让观察者(SimpleObserver类)达到观察被观察者(SimpleObservable类)的目的。

    然后还要复写update()方法,做数据改变后的一些处理。

    下面可以写一个简单的测试类来测试一下

    [java] view plain copy
    1. public class SimpleTest    
    2. {    
    3.    public static void main(String[] args){    
    4.       SimpleObservable doc = new SimpleObservable ();    
    5.       SimpleObserver view = new SimpleObserver (doc);    
    6.       doc.setData(1);    
    7.       doc.setData(2);    
    8.       doc.setData(2);    
    9.       doc.setData(3);     
    10.    }    
    11. }   

    运行结果如下
    [plain] view plain copy
    1. Data has changed to 1   
    2. Data has changed to 2  //第二次setData(2)时由于没有setChange,所以update没被调用  
    3. Data has changed to 3  

    下面介绍一个Observable类的其他一些属性和方法

    属性 ——

    [java] view plain copy
    1. // observers是一个List,保存着所有要通知的observer。      
    2. List<Observer> observers = new ArrayList<Observer>();  
    3. // changed是一个boolean型标志位,标志着数据是否改变了。  
    4. boolean changed = false;  

    方法 ——

    [java] view plain copy
    1. // 添加一个Observer到列表observers中  
    2. public void addObserver(Observer observer) {  
    3.     if (observer == null) {  
    4.         throw new NullPointerException();  
    5.     }  
    6.     synchronized (this) {  
    7.         if (!observers.contains(observer))  
    8.             observers.add(observer);  
    9.     }  
    10. }  
    11.   
    12. // 从列表observers中删除一个observer  
    13.   
    14. public synchronized void deleteObserver(Observer observer) {  
    15.     observers.remove(observer);  
    16. }  
    17.   
    18. // 清空列表observers  
    19. public synchronized void deleteObservers() {  
    20.     observers.clear();  
    21. }  
    22.   
    23. // 返回列表observers中observer的个数  
    24.   
    25. public int countObservers() {  
    26.     return observers.size();  
    27. }  
    28.   
    29.   
    30. // 重置数据改变标志位为未改变  
    31. protected void clearChanged() {   
    32. changed = false;  
    33. }  
    34.   
    35. // 将数据改变标志位设置为改变  
    36.   
    37. protected void setChanged() {   
    38.     changed = true;  
    39. }  
    40.   
    41.   
    42. // 判断标志位的值  
    43. public boolean hasChanged() {   
    44.     return changed;  
    45. }  
    46.   
    47. // 通知所有observer(无参)  
    48. public void notifyObservers() {  
    49.     notifyObservers(null);  
    50. }  
    51. // 通知所有observer(有参)  
    52. @SuppressWarnings("unchecked")  
    53. public void notifyObservers(Object data) {   
    54.     int size = 0;   
    55.     Observer[] arrays = null;   
    56.     synchronized (this) {   
    57.         if (hasChanged()) {   
    58.             clearChanged();   
    59.             size = observers.size();  
    60.             arrays = new Observer[size];   
    61.             observers.toArray(arrays);   
    62.         }   
    63.     }   
    64.     if (arrays != null) {   
    65.         for (Observer observer : arrays) {   
    66.             observer.update(this, data);   
    67.         }   
    68.     }  
    69. }  


    注意:在Observer对象销毁前一定要用deleteObserver将其从列表中删除,也就是在onDestroy()方法中调用deleteObserver()方法。

    不然因为还存在对象引用的关系,Observer对象不会被垃圾收集,造成内存泄漏,并且已死的Observer仍会被通知到,有可能造成意料外的错误,而且随着列表越来越大,notifyObservers操作也会越来越慢。

    下面2个工程是Observable与Observer的经典运用,是Android实现的单指拖动放大图片的操作

    两个例子:

    http://download.csdn.net/detail/tianjf0514/4237628

    http://download.csdn.net/download/tianjf0514/4237634

  • 相关阅读:
    oracle 内连接、外连接、自然连接、交叉连接练习
    oracle语句练习
    简单的oracle sql语句练习
    CountDownLatch 使用方法
    T1,T2,T3 三个线程顺序执行
    【2018 校招真题】斐波那契数列
    使用自己的域名解析 cnblogs 博客
    在 github 中新建仓库后,如何上传文件到这个仓库里面。
    数据库常用语句整理
    使用 JQuery 实现将 table 按照列排序
  • 原文地址:https://www.cnblogs.com/feng9exe/p/5754914.html
Copyright © 2011-2022 走看看