对象间的联动——观察者模式(十一)

观察者模式Java实现与自己实现的对比

  1. 不需要再定义观察者和目标接口(JDK已经定义)。
  2. 具体的目标实现里面不需要再维护观察者的注册信息,Java中的Observable类里面已经实现。
  3. 触发通知的方式有一点变化,要先调用setChanged方法,这个是Java为了帮助实现更精确的触发控制而提供的功能。
  4. 具体观察者的实现里面,update方法其实能同时支持推模型和拉模型,这个Java在定义的时候,已经考虑。

使用Java提供的接口实现天气实例

       定义目标对象类,并且继承Java中的Observable类:

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
package com.wy.observer.example_by_java;

import java.util.Observable;

//天气目标的具体实现类
public class ConcreteWeatherSubject extends Observable {

//天气情况的内容
private String content;

public String getContent() {
return content;
}

public void setContent(String content) {
this.content = content;
//天气情况有了,通知所有的观察者
//注意在通知前,在用Java中的Observer模式的时候,下面这句话不可少
setChanged();
//然后主动通知,推模型
notifyObservers(content);
//拉模型
//notifyObservers();

}
}

       定义观察者对象,并实现Observer接口:

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
package com.wy.observer.example_by_java;

import java.util.Observable;
import java.util.Observer;

/**
* Created by wy521angel on 2017/4/16.
*/

//具体的观察者对象
public class ConcreteObserver implements Observer {

//观察者名称的变量
private String observerName;

/**
* 第一个参数传递的目标应用,采用的是拉的方式
* 第二个参数推送的内容,采用的是推送的方式
*/
@Override
public void update(Observable observable, Object o) {
//推的方式
System.out.println(observerName + "收到了消息,目标推送过来的是" + o);
//拉的方式
System.out.println(observerName + "收到了消息,主动到目标对象中去拉,拉的内容是" + ((ConcreteWeatherSubject) observable).getContent());
}

public String getObserverName() {
return observerName;
}

public void setObserverName(String observerName) {
this.observerName = observerName;
}
}

       编写测试类:

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
package com.wy.observer.example_by_java;

/**
* Created by wy521angel on 2017/4/15.
*/
//测试类
public class Client {

public static void main(String[] args) {
// 创建天气作为一个目标,也可以说是被观察者
ConcreteWeatherSubject weather = new ConcreteWeatherSubject();

// 创建黄明的女朋友作为观察者
ConcreteObserver observerGirl = new ConcreteObserver();
observerGirl.setObserverName("黄明的女朋友");

// 创建黄明的母亲作为观察者
ConcreteObserver observerMum = new ConcreteObserver();
observerMum.setObserverName("黄明的母亲");

// 注册观察者
weather.addObserver(observerGirl);
weather.addObserver(observerMum);

// 目标发布天气
weather.setContent("明天天气晴朗,蓝天白云,气温28度");
}
}

       测试效果如下:

1
2
3
4
黄明的母亲收到了消息,目标推送过来的是明天天气晴朗,蓝天白云,气温28度
黄明的母亲收到了消息,主动到目标对象中去拉,拉的内容是明天天气晴朗,蓝天白云,气温28度
黄明的女朋友收到了消息,目标推送过来的是明天天气晴朗,蓝天白云,气温28度
黄明的女朋友收到了消息,主动到目标对象中去拉,拉的内容是明天天气晴朗,蓝天白云,气温28度

       代码地址详见 PatternTest

参考资料:
GerryZhang 利用Java提供的观察者模式实现

Fork me on GitHub