一、观察者模式介绍
在Java中通过Observable类和Observer接口实现了观察者模式。一个Observer对象监视着一个Observable对象的变化,当Observable对象发生变化时,Observer得到通知,就可以进行相应的工作。
如果画面A是显示数据库里面的数据,而画面B修改了数据库里面的数据,那么这时候画面A就要重新Load。这时候就可以用到观察者模式
二、观察者模式实现方法
java.util.Observable中有两个方法对Observer特别重要
①setChanged()方法
②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()方法做一些处理。
注意:
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 }
运行结果如下
- Data has changed to 1
- Data has changed to 2 //第二次setData(2)时由于没有setChange,所以update没被调用
- 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