观察者模式
观察者模式
案例引入
要求
气象站案例要求
- 1.气象站,可以将每天测量到的湿度,温度,气压等气象信息以公告的形式发布出去(发布到自己的网站或者第三方平台)。
- 2.需要设计开发新的api,便于其他第三方也能接入气象站的数据。
- 3.提供温度,气压,湿度的接口。
- 4.策略的数据更新后,实时的通知第三方。
普通方案实现案例
通过对气象项目的分析,我们可以初步设计一个WeatherData类。有温度(temperature),湿度(humidity),气压(pressure)三个属性,还有dataChange方法。
- 1.通过getXxx方法,可以让第三方接入,并得到相关信息。
- 2.气象站定时的调用dataChange()去更新数据,在数据更新时,当第三方再次获取时,就能得到最新的数据,当然也可以推送数据,即定时的将数据,推送到目标网站上。
代码实现
/**
* 1.核心类,包含最新的天气信息数据,可以推送给别人
* 2.含有 private CurrentConditions currentConditions;
* 3.数据更新时,主动调用currentConditions进行数据推送,这样接入方,就会及时看到最新数据
*
* @author 长名06
* @version 1.0
*/
public class WeatherData {
//温度
private float temperature;
//气压
private float pressure;
//湿度
private float humidity;
private CurrentConditions currentConditions;
public WeatherData(CurrentConditions c) {
this.currentConditions = c;
}
public float getTemperature() {
return temperature;
}
public float getPressure() {
return pressure;
}
public float getHumidity() {
return humidity;
}
public void dataChange() {
currentConditions.update(getTemperature(), getPressure(), getHumidity());
}
//当数据有更新时,就调用这个setData
public void setData(float temperature, float pressure, float humidity) {
this.temperature = temperature;
this.pressure = pressure;
this.humidity = humidity;
//信息改变时,将最新信息,推送给接入方
dataChange();
}
}
/**
* 显示今天天气情况,气象站自己的网站
* @author 长名06
* @version 1.0
*/
public class CurrentConditions {
//温度
private float temperature;
//气压
private float pressure;
//湿度
private float humidity;
//更新数据 由WeatherData来调用,
public void update(float temperature,float pressure,float humidity){
this.temperature = temperature;
this.pressure = pressure;
this.humidity = humidity;
display();
}
//展示数据
public void display(){
System.out.println("今天温度" + temperature);
System.out.println("今天气压" + pressure);
System.out.println("今天湿度" + humidity);
}
}
/**
* 观察者模式
* @author 长名06
* @version 1.0
*/
public class Client {
public static void main(String[] args) {
CurrentConditions currentConditions = new CurrentConditions();
WeatherData weatherData = new WeatherData(currentConditions);
weatherData.setData(30,100,25);
System.out.println("=====天气变化=====");
weatherData.setData(35,100,30);
}
}
问题分析
- 1.无法在运行时,动态的添加第三方。
- 2.在WeatherData中,当增加一个第三方,都需要创建一个对应的第三方的公告板对象,并加入到dataChange,不利于维护,也不是动态加入。
- 3.违反了ocp(开闭原则),=> 使用观察者模式。
观察者模式原理
观察者模式,类似订牛奶的业务,在观察者模式下,有以下角色,奶站/气象局(Subject),用户/第三方网站(Observer),Subject中有登记注册,移除和通知接口方法,register()注册,remove()移除,notify()通知注册用户,根据不同需求,不同实现,可以通知用户取数据,也可以推送给用户数据,也可以更新数据,Observer中接收输入,也就是修改数据的方法update()。
观察者模式:对象之间多对一依赖的一种设计方案,被依赖的对象为Subject,依赖的对象为Observer,Subject通知Observer数据变化,类似定牛奶的业务,Subject是1,Observer是多。
观察者模式实现案例
uml图
代码实现
/**
* @author 长名06
* @version 1.0
*/
public interface Subject {
public void register(Observer o);
public void remove(Observer o);
public void notifies();
}
public interface Observer {
public void update(float temperature,float pressure,float humidity);
}
/**
* 1.核心类,包含最新的天气信息数据,可以推送给别人
* 2.含有 观察者集合。使用ArrayList管理
* 3.数据更新时,主动调用观察者集合进行数据推送,这样接入方,就会及时看到最新数据
* @author 长名06
* @version 1.0
*/
public class WeatherData implements Subject{
//温度
private float temperature;
//气压
private float pressure;
//湿度
private float humidity;
private List<Observer> observers = new ArrayList<>();
public float getTemperature() {
return temperature;
}
public float getPressure() {
return pressure;
}
public float getHumidity() {
return humidity;
}
public void dataChange(){
notifies();//通知所有注册用户
}
//当数据有更新时,就调用这个setData
public void setData(float temperature, float pressure, float humidity) {
this.temperature = temperature;
this.pressure = pressure;
this.humidity = humidity;
//信息改变时,将最新信息,推送给接入方
dataChange();
}
@Override
public void register(Observer o) {
observers.add(o);
}
@Override
public void remove(Observer o) {
if(observers.contains(o)) {
observers.remove(o);
}
}
@Override
public void notifies() {
for(Observer o : observers){
o.update(this.temperature,this.pressure,this.humidity);
}
}
}
public class TenXun implements Observer{
//温度
private float temperature;
//气压
private float pressure;
//湿度
private float humidity;
//更新数据 由WeatherData来调用,
@Override
public void update(float temperature,float pressure,float humidity){
this.temperature = temperature;
this.pressure = pressure;
this.humidity = humidity;
display();
}
//展示数据
public void display(){
System.out.println("====腾讯网站====");
System.out.println("腾讯 今天温度" + temperature);
System.out.println("腾讯 今天气压" + pressure);
System.out.println("腾讯 今天湿度" + humidity);
}
}
/**
* @author 长名06
* @version 1.0
*/
public class XingLang implements Observer{
//温度
private float temperature;
//气压
private float pressure;
//湿度
private float humidity;
//更新数据 由WeatherData来调用,
@Override
public void update(float temperature,float pressure,float humidity){
this.temperature = temperature;
this.pressure = pressure;
this.humidity = humidity;
display();
}
//展示数据
public void display(){
System.out.println("====新浪网站====");
System.out.println("新浪 今天温度" + temperature);
System.out.println("新浪 今天气压" + pressure);
System.out.println("新浪 今天湿度" + humidity);
}
}
public class Baidu implements Observer {
//温度
private float temperature;
//气压
private float pressure;
//湿度
private float humidity;
//更新数据 由WeatherData来调用,
@Override
public void update(float temperature,float pressure,float humidity){
this.temperature = temperature;
this.pressure = pressure;
this.humidity = humidity;
display();
}
//展示数据
public void display(){
System.out.println("====百度网站====");
System.out.println("百度 今天温度" + temperature);
System.out.println("百度 今天气压" + pressure);
System.out.println("百度 今天湿度" + humidity);
}
}
/**
* @author 长名06
* @version 1.0
*/
public class Client {
public static void main(String[] args) {
WeatherData weatherData = new WeatherData();
Baidu baidu = new Baidu();
TenXun tenXun = new TenXun();
XingLang xingLang = new XingLang();
weatherData.register(baidu);
weatherData.register(tenXun);
weatherData.register(xingLang);
weatherData.setData(20,100,30.3F);
weatherData.remove(xingLang);
System.out.println("====某个用户不订阅了====");
weatherData.setData(20,100,30.3F);
}
}
观察者模式优势
1.使用观察者模式后,以集合的形式来管理用户(Observer),包括注册,移除和通知。
2.这样我们增加观察者(可以理解为一个新的用户),就不需要取修改核心类,WeatherData不用修改代码,遵守了ocp。
观察者模式在JDK源码分析
1.JDK的ObServable类就使用了观察者模式。
2.角色分析
2.1 Observable的作用和地位等价于我们前面讲过的Subject.
2.2 Observable是类,不是接口,类中也实现了核心的方法,即管理Observable的方法,add,remove,notify等。
2.3 Observer的作用和地位等价于我们前面讲过的Observer,有update。
2.4 Observable和Observer的使用方法和前面讲过的一样,只是Observable是类,通过继承来实现观察者模式。
只是为了记录自己的学习历程,且本人水平有限,不对之处,请指正。