hello world

随笔 - 2, 文章 - 63, 评论 - 0, 引用 - 0
数据加载中……

Java_观察者模式(Observable和Observer)

一、观察者模式介绍

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

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

二、观察者模式实现方法

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

①setChanged()方法

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)方法

 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是属于自己的才做一些处理。

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


下面举个例子加以说明:

 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(),否则什么都不干。

 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()方法,做数据改变后的一些处理。

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

 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 }  

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

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

属性 ——


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

方法 ——


 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

posted on 2017-07-25 10:39 听风 阅读(116) 评论(0)  编辑  收藏 所属分类: JAVA


只有注册用户登录后才能发表评论。


网站导航: