设计模式之观察者模式
Posted xiaojimanman
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了设计模式之观察者模式相关的知识,希望对你有一定的参考价值。
目录
观察者模式介绍
观察者模式定义了对象之间的一对多的依赖,这样依赖,当一个对象改变状态时,它的所有依赖者都会受到通知并自动更新。
气象站
下面通过气象站的事例来介绍观察者模式
最初的气象应用
最开始气象站有三个感应装置,分别为温度(temperature)、湿度(humidity)和气压(pressure),显示装置也就只有一个布告板(具体如下),气象站的三个感应装置获取到的最新数据后要展示在布告板上,因此我们可能设计如下的实现:
当前天气情况:
气温:25℃
湿度:60
气压:1atm
布告板接口
public interface Display
void display (double temperature, double humidity, double pressure);
布告板实现
public class CurrentDisplay implements Display
public void display (double temperature, double humidity, double pressure)
String content = String.format("当前天气情况:\\n气温:%s℃\\n湿度:%s\\n气压:%satm", temperature, humidity, pressure);
System.out.println(content);
气象台监控
public class WeatherData
private double temperature;
private double humidity;
private double pressure;
public void weatherDataChange(double temperature, double humidity, double pressure)
this.temperature = temperature;
this.humidity = humidity;
this.pressure = pressure;
updateDisplay();
private void updateDisplay()
new CurrentDisplay().display(temperature, humidity, pressure);
测试
public class Test
public static void main(String[] args)
WeatherData weatherData = new WeatherData();
weatherData.weatherDataChange(25D, 72D, 1.1D);
输出结果
当前天气情况:
气温:25.0℃
湿度:72.0
气压:1.1atm
布告板发展
随着业务的发展,布告板的展现形式也越来越多种多样,按照上述的形式,我们只能在WeatherData:updateDisplay()下面不断的新增需要通知的布告板,这个看起来没有什么问题,但是细想下每次新增一个布告板,我们都需要在WeatherData:updateDisplay()下面新加一个通知,没移除一个布告板,都需要将WeatherData:updateDisplay()下面对应的进行移除,天气数据和布告板紧紧的耦合在一起,这个并不符合我们的高内聚低耦合的设计原则,因此我们需要再次进行优化,设计为观察者模式。
气象站观察者模式
针对上述,布告板我们无需进行改变,我们对WeatherData进行优化,具体如下(这里我们只介绍设计模式,不考虑线程安全):
public class WeatherData
private double temperature;
private double humidity;
private double pressure;
private List<Display> displays = new ArrayList<Display>();
//注册观察者
public void addDisplay(Display display)
displays.add(display);
//取消注册
public void removeDisplay(Display display)
int i = displays.indexOf(display);
if (i >= 0)
displays.remove(display);
public void weatherDataChange(double temperature, double humidity, double pressure)
this.temperature = temperature;
this.humidity = humidity;
this.pressure = pressure;
updateDisplay();
private void updateDisplay()
for (Display display : displays)
display.display(temperature, humidity, pressure);
测试
public class Test
public static void main(String[] args)
WeatherData weatherData = new WeatherData();
Display display1 = new CurrentDisplay();
Display display2 = new Current2Display();
Display display3 = new CurrentDisplay();
weatherData.addDisplay(display1);
weatherData.addDisplay(display2);
weatherData.addDisplay(display3);
System.out.println("----------注册三个观察者----------");
weatherData.weatherDataChange(25D, 72D, 1.1D);
weatherData.removeDisplay(display3);
System.out.println("----------取消第三个观察者----------");
weatherData.weatherDataChange(28D, 77D, 0.9D);
输出结果
----------注册三个观察者----------
当前天气情况:
气温:25.0℃
湿度:72.0
气压:1.1atm
当前天气情况2:
气温:25.0℃
湿度:72.0
气压:1.1atm
当前天气情况:
气温:25.0℃
湿度:72.0
气压:1.1atm
----------取消第三个观察者----------
当前天气情况:
气温:28.0℃
湿度:77.0
气压:0.9atm
当前天气情况2:
气温:28.0℃
湿度:77.0
气压:0.9atm
这样我们就把布告板从气象台中抽象出来,后续再添加布告板,我们也无需再次修改WeatherData代码。
Java内置实现观察者
Java内置中提供了 java.util.Observer接口和java.util.Observable类来实现观察者模式,下面我们就使用Java内置工具来实现上述气象台的观察者模式。
WeatherData
package com.lulei.study.design.patterns.observer;
import lombok.Data;
import java.util.Observable;
/**
* Created by lulei on 2019/4/16.
*/
@Data
public class WeatherData extends Observable
private double temperature;
private double humidity;
private double pressure;
public void weatherDataChange(double temperature, double humidity, double pressure)
this.temperature = temperature;
this.humidity = humidity;
this.pressure = pressure;
updateDisplay();
private void updateDisplay()
//在调用notifyObservers()之前,先调用setChanged()来指示状态已经改变
setChanged();
//这里我们没有传送数据,表示我们采用的做法是拉
notifyObservers();
Display
package com.lulei.study.design.patterns.observer;
/**
* Created by lulei on 2019/4/16.
*/
public interface Display
void display (double temperature, double humidity, double pressure);
CurrentDisplay
package com.lulei.study.design.patterns.observer;
import java.util.Observable;
import java.util.Observer;
/**
* Created by lulei on 2019/4/16.
*/
public class CurrentDisplay implements Observer, Display
public CurrentDisplay(Observable observable)
observable.addObserver(this);
public void display (double temperature, double humidity, double pressure)
String content = String.format("当前天气情况:\\n气温:%s℃\\n湿度:%s\\n气压:%satm", temperature, humidity, pressure);
System.out.println(content);
public void update(Observable observable, Object arg)
if (observable instanceof WeatherData)
WeatherData weatherData = (WeatherData)observable;
display(weatherData.getTemperature(), weatherData.getHumidity(), weatherData.getPressure());
Current2Display
package com.lulei.study.design.patterns.observer;
import java.util.Observable;
import java.util.Observer;
/**
* Created by lulei on 2019/4/16.
*/
public class Current2Display implements Observer, Display
public Current2Display(Observable observable)
observable.addObserver(this);
public void display (double temperature, double humidity, double pressure)
String content = String.format("当前天气情况2:\\n气温:%s℃\\n湿度:%s\\n气压:%satm", temperature, humidity, pressure);
System.out.println(content);
public void update(Observable observable, Object arg)
if (observable instanceof WeatherData)
WeatherData weatherData = (WeatherData)observable;
display(weatherData.getTemperature(), weatherData.getHumidity(), weatherData.getPressure());
Test
package com.lulei.study.design.patterns.observer;
import java.util.Observer;
/**
* Created by lulei on 2019/4/16.
*/
public class Test
public static void main(String[] args)
WeatherData weatherData = new WeatherData();
Observer display1 = new CurrentDisplay(weatherData);
Observer display2 = new Current2Display(weatherData);
Observer display3 = new CurrentDisplay(weatherData);
System.out.println("----------注册三个观察者----------");
weatherData.weatherDataChange(25D, 72D, 1.1D);
weatherData.deleteObserver(display3);
System.out.println("----------取消第三个观察者----------");
weatherData.weatherDataChange(28D, 77D, 0.9D);
输出结果
----------注册三个观察者----------
当前天气情况:
气温:25.0℃
湿度:72.0
气压:1.1atm
当前天气情况2:
气温:25.0℃
湿度:72.0
气压:1.1atm
当前天气情况:
气温:25.0℃
湿度:72.0
气压:1.1atm
----------取消第三个观察者----------
当前天气情况2:
气温:28.0℃
湿度:77.0
气压:0.9atm
当前天气情况:
气温:28.0℃
湿度:77.0
气压:0.9atm
以上是关于设计模式之观察者模式的主要内容,如果未能解决你的问题,请参考以下文章