观察者模式是软件设计模式中的一种,使用也比较普遍,尤其是在GUI编程中。关于设计模式的文章,网络上写的都比较多,而且很多文章写的也不错,虽然说有一种重复早轮子的嫌疑,但此轮子非彼轮子,侧重点不同,思路也不同,讲述方式也不近相同。
关键要素
主题:
主题是观察者观察的对象,一个主题必须具备下面三个特征。
- 持有监听的观察者的引用
- 支持增加和删除观察者
- 主题状态改变,通知观察者
观察者:
当主题发生变化,收到通知进行具体的处理是观察者必须具备的特征。
为什么要用这种模式
这里举一个例子来说明,牛奶送奶站就是主题,订奶客户为监听者,客户从送奶站订阅牛奶后,会每天收到牛奶。如果客户不想订阅了,可以取消,以后就不会收到牛奶。
松耦合
观察者增加或删除无需修改主题的代码,只需调用主题对应的增加或者删除的方法即可。
主题只负责通知观察者,但无需了解观察者如何处理通知。举个例子,送奶站只负责送递牛奶,不关心客户是喝掉还是洗脸。
观察者只需等待主题通知,无需观察主题相关的细节。还是那个例子,客户只需关心送奶站送到牛奶,不关心牛奶由哪个快递人员,使用何种交通工具送达。
Java实现观察者模式
1. Java自带的实现
类图
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
|
/** * 观察目标 继承自 java.util.Observable * @author stone * */ public class UpdateObservable extends Observable { private int data; public UpdateObservable(Observer observer) { addObserver(observer); /* * add other observer */ } public int getData() { return data; } public void setData( int data) { if (data != this .data) { this .data = data; setChanged(); //标记 改变, 只有标记后才能通知到 notifyObservers(); //通知 } } @Override public synchronized void addObserver(Observer o) { super .addObserver(o); } @Override public synchronized void deleteObserver(Observer o) { super .deleteObserver(o); } @Override public void notifyObservers() { super .notifyObservers(); } @Override public void notifyObservers(Object arg) { super .notifyObservers(arg); } @Override public synchronized void deleteObservers() { super .deleteObservers(); } @Override protected synchronized void setChanged() { super .setChanged(); } @Override protected synchronized void clearChanged() { super .clearChanged(); } @Override public synchronized boolean hasChanged() { return super .hasChanged(); } @Override public synchronized int countObservers() { return super .countObservers(); } } |
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
|
/** * 观察者 实现 java.util.Observer接口 * @author stone * */ public class UpdateObserver implements Observer { @Override public void update(Observable o, Object arg) { System.out.println( "接收到数据变化的通知:" ); if (o instanceof UpdateObservable) { UpdateObservable uo = (UpdateObservable) o; System.out.print( "数据变更为:" + uo.getData()); } } } |
2. 自定义的观察模型
类图
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
|
/** * 抽象观察者 Observer * 观察 更新 * @author stone * */ public interface IWatcher { /* * 通知接口: * 1. 简单通知 * 2. 观察者需要目标的变化的数据,那么可以将目标用作参数, 见Java的Observer和Observable */ // void update(IWatched watched); void update(); } |
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
|
/** * 抽象目标 Subject * 提供注册和删除观察者对象的接口, 及通知观察者进行观察的接口 * 及目标 自身被观察的业务的接口 * @author stone * */ public interface IWatchedSubject { public void add(IWatcher watch); public void remove(IWatcher watch); public void notifyWhatchers(); public void update(); //被观察业务变化的接口 } |
1
2
3
4
5
6
7
8
9
10
11
12
13
14
|
/** * 具体观察者 Concrete Observer * * @author stone * */ public class UpdateWatcher implements IWatcher { @Override public void update() { System.out.println( this + "观察到:目标已经更新了" ); } } |
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
|
/** * 具体目标角色 Concrete Subject * @author stone * */ public class UpdateWatchedSubject implements IWatchedSubject { private List<IWatcher> list; public UpdateWatchedSubject() { this .list = new ArrayList<IWatcher>(); } @Override public void add(IWatcher watch) { this .list.add(watch); } @Override public void remove(IWatcher watch) { this .list.remove(watch); } @Override public void notifyWhatchers() { for (IWatcher watcher : list) { watcher.update(); } } @Override public void update() { System.out.println( "目标更新中...." ); notifyWhatchers(); } } |
监听器是观察者的一种实现:
类图
1
2
3
4
5
6
7
8
|
/** * 监听 用户在注册后 * @author stone * */ public interface IRegisterListener { void onRegistered(); } |
1
2
3
4
5
6
7
8
|
/** * 监听 当用户登录后 * @author stone * */ public interface ILoginListener { void onLogined(); } |
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
|
/* * 监听器 是观察者模式的一种实现 * 一些需要监听的业务接口上添加 监听器,调用监听器的相应方法,实现监听 */ public class User { public void register(IRegisterListener register) { /* * do ... register */ System.out.println("正在注册中..."); //注册后 register.onRegistered(); } public void login(ILoginListener login) { /* * do ... login */ System.out.println( "正在登录中..." ); //登录后 login.onLogined(); } } |
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
|
/** * 观察者(Observer)模式 行为型模式 * 观察者模式定义了一种一对多的依赖关系,让多个观察者对象同时观察某一个目标对象。 * 这个目标对象在状态上发生变化时,会通知所有观察者对象,让它们能够自动更新自己 * 目标对象中需要有添加、移除、通知 观察者的接口 * * @author stone */ public class Test { public static void main(String[] args) { /* * 使用Java自带的Observer接口和Observable类 */ UpdateObservable observable = new UpdateObservable(new UpdateObserver()); observable.setData(99); System.out.println(""); System.out.println(""); /* * 自定义的观察者模型 */ IWatchedSubject watched = new UpdateWatchedSubject(); watched.add(new UpdateWatcher()); watched.add(new UpdateWatcher()); watched.update(); System.out.println(""); /* * 子模式-监听器 */ User user = new User(); user.register( new IRegisterListener() { @Override public void onRegistered() { System.out.println( "监听到注册后。。。" ); } }); user.login( new ILoginListener() { @Override public void onLogined() { System.out.println( "监听到登录后。。。" ); } }); } } |
打印
1
2
3
4
5
6
7
8
9
10
11
|
接收到数据变化的通知: 数据变更为:99 目标更新中.... observer.UpdateWatcher@457471e0观察到:目标已经更新了 observer.UpdateWatcher@5fe04cbf观察到:目标已经更新了 正在注册中... 监听到注册后。。。 正在登录中... 监听到登录后。。。 |