转自:$Java设计模式之——观察者模式(Observer)
(一)观察者模式简介
1、定义:定义对象间一种一对多的依赖关系,一个对象状态发生改变时,所有依赖它的对象都会接到通知并作出相应的响应。
2、应用场景:
(1)GUI系统
(2)订阅-发布系统
(3)事件多级触发场景
(4)当一个对象改变时需要通知其他对象,但不知道有其他对象具体有哪些时
3、UML类图
(二)观察者模式实例
1、假设有个珠宝公司要运送一批钻石,强盗也盯上这批钻石了,准备在运输途中抢劫,而珠宝公司雇佣的保镖要全程对钻石进行保护,警察也派出警车护航,关系如下图:

2、代码如下:
(1)抽象观察者接口:
1 /**
2 * 抽象观察者
3 *
4 */
5
6 public interface Watcher {
7 // 对被观察者状态变化做出响应的抽象方法
8 public void update(String msg);
9 }
(2)抽象被观察者接口:
1 /**
2 * 抽象被观察者
3 *
4 */
5
6 public interface Watched {
7 // 添加观察者
8 public void addWatcher(Watcher watcher);
9
10 // 移除观察者
11 public void removeWatcher(Watcher watcher);
12
13 // 通知观察者
14 public void notifyWatchers(String msg);
15 }
(3)保镖类:
1 /**
2 * 保镖类,实现Watcher接口
3 *
4 */
5
6 public class Security implements Watcher {
7
8 @Override
9 public void update(String msg) {
10 System.out.println("保镖收到消息:" + msg + "。保镖开始保护!");
11 }
12
13 }
(4)警察类:
1 /**
2 * 警察类,实现Watcher接口
3 *
4 */
5
6 public class Police implements Watcher {
7
8 @Override
9 public void update(String msg) {
10 System.out.println("警察收到消息:" + msg + "。警察开始派警车护航!");
11 }
12
13 }
(5)强盗类:
/**
* 强盗类,实现Watcher接口
*
*/
public class Thief implements Watcher {
@Override
public void update(String msg) {
System.out.println("收到消息:" + msg + "。强盗准备动手!");
}
}
(6)珠宝运输类:
1 /**
2 * 具体的被观察者
3 *
4 */
5
6 public class Transporter implements Watched {
7
8 List<Watcher> wathcerList = new ArrayList<Watcher>();
9
10 @Override
11 public void addWatcher(Watcher watcher) {
12 wathcerList.add(watcher);
13 }
14
15 @Override
16 public void removeWatcher(Watcher watcher) {
17 wathcerList.remove(watcher);
18 }
19
20 @Override
21 public void notifyWatchers(String msg) {
22 for (Watcher w : wathcerList) {
23 w.update(msg);
24 }
25 }
26
27 }
(6)测试类:
1 public class Test {
2 public static void main(String[] args) {
3 Security s = new Security();
4 Thief t = new Thief();
5 Police p = new Police();
6
7 Transporter transPorter = new Transporter();
8 transPorter.addWatcher(s);
9 transPorter.addWatcher(t);
10 transPorter.addWatcher(p);
11
12 transPorter.notifyWatchers("运输车队开始出发了");
13
14 transPorter.removeWatcher(t);
15 transPorter.notifyWatchers("运输车队摆脱了强盗");
16 }
17 }
(7)输出结果:
保镖收到消息:运输车队开始出发了。保镖开始保护!
收到消息:运输车队开始出发了。强盗准备动手!
警察收到消息:运输车队开始出发了。警察开始派警车护航!
保镖收到消息:运输车队摆脱了强盗。保镖开始保护!
警察收到消息:运输车队摆脱了强盗。警察开始派警车护航!
以上理解起来可能有些抽象,下面再举个栗子。
下面通过一个例子来说明:
假设如下的情况:
AccountManager 对象能够观察 Account,这样,在帐户状态改变时,它们可以向销售人员发送一封电子邮件。
代码如下:
public class Account { private int state; private String name; public String getName() { return name; } public Account(String name) { super(); this.name = name; } public int getState() { return state; } public void setState(int state) { this.state = state; } @Override public String toString() { return name; } } public class AccountManager { public void sendEmail(Account account) { System.out.println("send Email:" + account); } }
来看一下java代码是如何实现观察者模式的
Java 语言的观察者
虽然实现的差异很明显,但在它们之间还是有一些相似之处。不论如何实现观察者,代码中都必须回答以下 4 个问题:
1. 哪个对象是主体,哪个对象是观察者?
2. 什么时候主体应当向它的观察者发送通知?
3. 当接收到通知时,观察者应该做什么?
4. 观察关系应当在什么时候开始,什么时候终止?
角色定义
首先从标记器接口来分配角色开始。Observer 接口只定义了一个方法:update(),它对应着 Subject 发送通知时执行的操作。 Subject 承担着更多的职责。它的标记器接口定义了两个方法,一个用来跟踪观察者,另一个用来通知事件的那些观察者。
public interface Observer { public void update(Subject subject); } public interface Subject { public void addObserver(Observer o); public void removeObserver(Observer o); public void notifyObservers(); }
一旦定义了这些角色,就可以把它们应用到系统中对应的角色上。
应用观察者角色
public class AccountManager implements Observer { public void update(Subject subject) { sendEmail((Account) subject); } }
跟踪和通知观察者
一旦这项工作完成,就可以转移到Subject。在这里,要对 Account进行修改:
private Set observers = new HashSet(); public void addObserver(Observer o) { observers.add(o); } public void removeObserver(Observer o) { observers.remove(o); } public void notifyObservers() { for (Observer o : observers) { o.update(this); } }
触发事件
现在已经把类调整到它们在模式中的角色上了。但是,还需要回过头来,在对应的事件发生时触发通知。
Account类 public void setState(int state) { if (this.state != state) { this.state = state; notifyObservers(); } }
启动观察关系
public class ObserverClient { public static void main(String[] args) { AccountManager manager = new AccountManager(); AccountManager manager2 = new AccountManager(); Account account = new Account("Account1"); account.addObserver(manager); account.addObserver(manager2); account.setState(1); } }

浙公网安备 33010602011771号