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

观察者模式的两种模式

       观察者模式的实现有两种方式:推模型和拉模型。

简介

  1. 推模型:目标对象主动向观察者推送目标的详细信息 ; 推送的信息通常是目标信息的全部或部分信息。
  2. 拉模型:目标对象在通知观察者的时候,只传递少量信息 ;如果观察者需要更具体的信息,由观察者主动到目标对象中获取,相当于是观察者从目标对象中拉数据;一般这种模型的实现中,会把目标对象自身通过update方法传递给观察者。

       对象间的联动——观察者模式(八)的天气实例,使用的是拉模型,接下来对该实例进行修改,实现推模型。

实现推模型

       首先需要将Observer中的update方法进行修改,如下所示:

1
2
3
4
5
6
7
8
9
package com.wy.observer.example;

public interface Observer {

/**
* 更新的接口(推模型)
*/
public void update(String content);
}

       将update的参数由WeatherSubject修改成了String。

       然后将ConcreteObserver中继承的update方法进行修改,如下所示:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
package com.wy.observer.example;

public class ConcreteObserver implements Observer {

...

/**
* 获取目标类的状态同步到观察者的状态中(推模型)
*
* @param content
*/
@Override
public void update(String content) {
weatherContent = content;
System.out.println(observerName + "收到了" + weatherContent + "," + remindThing);
}

...
}

       接着把WeatherSubject中的notifyObservers方法进行适当的修改,如下所示:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
package com.wy.observer.example;

import java.util.ArrayList;
import java.util.List;

public class WeatherSubject {

...

/**
* 通知所有已经订阅了天气的人
*/
protected void notifyObservers(String content) {
for (Observer observer : observers) {
observer.update(content);
}
}

}

       最后还需要将ConcreteWeatherSubject中的 setWeatherContent方法进行修改,如下所示:

1
2
3
4
5
6
7
8
9
10
11
package com.wy.observer.example;

public class ConcreteWeatherSubject extends WeatherSubject {

……

public void setWeatherContent(String weatherContent) {
this.weatherContent = weatherContent;
this.notifyObservers(weatherContent);//推模型
}
}

       测试代码无需变动,运行结果与拉模型是一样的:

1
2
黄明的女朋友收到了明天天气晴朗,蓝天白云,气温28度,是我们的第一次约会,地点街心公园,不见不散哦
黄明的母亲收到了明天天气晴朗,蓝天白云,气温28度,是一个购物的好日子,明天去天虹扫货

       代码地址详见 PatternTest

两种模型的比较

       推模型是假定目标对象知道观察者需要的数据;拉模型是目标对象不知道观察者具体需要什么数据,因此把自身传给观察者,由观察者来取值。

       推模型会使观察者对象难于复用;拉模型下,update方法的参数是目标对象本身,基本上可以适应于各种情况的需要。

参考资料:
GerryZhang 实现的两种方式:推模型和拉模型

Fork me on GitHub