对于观察者模式,其实Java已经为我们提供了已有的接口和类。对于订阅者(Subscribe,观察者)Java为我们提供了一个接口,JDK源码如下:
1 package java.util;
2
3 public interface Observer {
4 void update(Observable o, Object arg);
5 }
和我们上一篇实现的观察者一样,仅提供一个update方法用于接收通知者的通知做出相应改变。
我们再来看看Java为我们提供了一个怎样的通知者(Publish,发布者),JDK源码如下:
1 package java.util;
2
3 public class Observable {
4 private boolean changed = false; //是否改变状态
5 private Vector obs; //Vector利用同步方法来线程安全,线程安全在多线程情况下不会造成数据混乱
6
7 public Observable() {
8 obs = new Vector();
9 }
10
11 public synchronized void addObserver(Observer o) {
12 if (o == null)
13 throw new NullPointerException();
14 if (!obs.contains(o)) {
15 obs.addElement(o);
16 }
17 }
18
19 public synchronized void deleteObserver(Observer o) {
20 obs.removeElement(o);
21 }
22
23 public void notifyObservers() {
24 notifyObservers(null);
25 }
26
27 public void notifyObservers(Object arg) {
28 Object[] arrLocal;
29
30 synchronized (this) {
31 if (!changed) //状态值未改变时返回,不通知
32 return;
33 arrLocal = obs.toArray(); //将Vector转换成数组
34 clearChanged(); //重置状态
35 }
36
37 for (int i = arrLocal.length-1; i>=0; i--)
38 ((Observer)arrLocal[i]).update(this, arg);
39 }
40
41 public synchronized void deleteObservers() {
42 obs.removeAllElements();
43 }
44
45 protected synchronized void setChanged() {
46 changed = true;
47 }
48
49 protected synchronized void clearChanged() {
50 changed = false;
51 }
52
53 public synchronized boolean hasChanged() {
54 return changed;
55 }
56
57 public synchronized int countObservers() {
58 return obs.size();
59 }
60 }
不得不说,Java源码考虑得就是比自己写的要好。首先,使用Vector,Vector相比于ArrayList来说,它是线程安全的。其次,在添加和删除观察者时对两个方法使用了synchronized关键字,这都是在为多线程考虑。确实Java源码并不是那么可怕,它同样也是由一些最简单最基础的组合而来。
接下来我们来看看是如何利用Java提供的接口和方法来实现观察者模式。
1 package day_10_observer_jdk;
2
3 import java.util.Observable;
4 import java.util.Observer;
5
6 /**
7 * 实现java.util.Observer接口的观察者
8 * @author turbo
9 *
10 * 2016年9月14日
11 */
12 public class Subscribe implements Observer {
13
14 public Subscribe(Observable o){
15 o.addObserver(this); //将该观察者放入待通知观察者里
16 }
17 /* (non-Javadoc)
18 * @see java.util.Observer#update(java.util.Observable, java.lang.Object)
19 */
20 @Override
21 public void update(Observable o, Object arg) {
22 System.out.println("收到通知:" + ((Publish)o).getData());
23 }
24
25 }
1 package day_10_observer_jdk;
2
3 import java.util.Observable;
4
5 /**
6 * 继承java.util.Observable的通知者
7 * @author turbo
8 *
9 * 2016年9月14日
10 */
11 public class Publish extends Observable {
12 private String data = "";
13
14 public String getData() {
15 return data;
16 }
17
18 public void setData(String data) {
19 if (!this.data.equals(data)){
20 this.data = data;
21 setChanged(); //改变通知者的状态
22 }
23 notifyObservers(); //调用父类Observable方法,通知所有观察者
24 }
25 }
客户端测试代码:
1 package day_10_observer_jdk;
2
3 /**
4 * @author turbo
5 *
6 * 2016年9月14日
7 */
8 public class Main {
9
10 /**
11 * @param args
12 */
13 public static void main(String[] args) {
14 Publish publish = new Publish();
15 Subscribe subscribe = new Subscribe(publish);
16
17 publish.setData("开始");
18 }
19
20 }
这样我们就利用了Java给我们提供的Observer接口和Observable类实现了观察者模式。上一篇我们提到了事件委托,我们在下一篇来了解一下什么是事件委托。