一,背景
观察者模式在我们的工作中很多地方都有用到,如果学会了会为我们代码的健壮性增色不少.首先所谓观察者模式,是一对多的,本例中以气象站为例,一个气象站就相当于一个主题,也就是消息的提供者,而多个天气显示器就是相当于我们的观察者,也就是消息的接收者.当气象站的天气发生变化时,多个显示器显示的信息也会发生变化.
二,设计思路
首先我们应该在气象站中留有注册显示器的方法,移除显示器的方法,以及通知天气变化的方法
其次我们写一个显示器接口,其中我们应该有一个更新天气变化的方法
在气象站与显示器交互的过程中我们只知道他们的接口方法.而并不知道具体是怎么实现的.
三,类图
四,代码
1,主题(被观察者)
package com.yxf.designpattern.observer.gama;
/**
* 主题接口
* @Description
* @author yxf
* @time 2018-8-21上午10:17:12
*/
public interface Subject {
void registerObserver(Observer observer);
void removeObserver(Observer observer);
void notifyObserver();
void setChange();
void clearChange();
boolean hasChange();
}
package com.yxf.designpattern.observer.gama;
import java.util.ArrayList;
import java.util.List;
/**
* 主题实现类
* @Description
* @author yxf
* @time 2018-8-21上午10:26:31
*/
public class WeatherData implements Subject {
private List<Observer> observerList;
private boolean change;
private Weather weather;
public WeatherData(){
if(null == observerList){
observerList = new ArrayList<Observer>();
}
}
@Override
public void registerObserver(Observer observer) {
observerList.add(observer);
}
@Override
public void removeObserver(Observer observer) {
if(observerList.indexOf(observer) == -1){
return;
}
observerList.remove(observer);
}
@Override
public void notifyObserver() {
if(!change){
return;
}
for (int i = 0; i < observerList.size(); i++) {
observerList.get(i).update(weather);
}
clearChange();
}
public void changeMethod(Weather weather){
setWeather(weather);
notifyObserver();
}
@Override
public void setChange() {
change = true;
}
@Override
public void clearChange() {
change = false;
}
@Override
public boolean hasChange() {
return change;
}
public void setWeather(Weather weather){
this.weather = weather;
}
}
2,观察者
package com.yxf.designpattern.observer.gama;
/**
* 观察者
* @Description
* @author yxf
* @time 2018-8-21上午10:17:05
*/
public interface Observer {
/**
* 更新天气
* @description
* @param
* @return
*/
void update(Weather weather);
}
package com.yxf.designpattern.observer.gama;
/**
* 显示接口
* @Description
* @author yxf
* @time 2018-8-21上午10:37:27
*/
public interface DisplayElement {
void display();
}
package com.yxf.designpattern.observer.gama;
/**
* 温度显示器
* @Description
* @author yxf
* @time 2018-8-21上午11:45:17
*/
public class TempDisplay implements Observer,DisplayElement{
private Weather weather;
@Override
public void display() {
System.out.println("温度显示器显示的当前温度为:"+weather.getTemp());
}
@Override
public void update(Weather weather) {
this.weather = weather;
display();
}
}
package com.yxf.designpattern.observer.gama;
/**
* 湿热显示器
* @Description
* @author yxf
* @time 2018-8-21上午10:53:07
*/
public class MuggyDisplay implements Observer,DisplayElement{
private Weather weather;
@Override
public void display() {
System.out.println("湿热显示器显示的湿热比为:"+weather.getHumidity()/weather.getTemp());
}
@Override
public void update(Weather weather) {
this.weather = weather;
display();
}
}
package com.yxf.designpattern.observer.gama;
/**
* 压力显示器
* @Description
* @author yxf
* @time 2018-8-21上午11:12:20
*/
public class PressureDisplay implements Observer,DisplayElement{
public Weather weather;
@Override
public void display() {
System.out.println("压力显示器显示的压力为:"+weather.getPressure());
}
@Override
public void update(Weather weather) {
this.weather = weather;
display();
}
}
package com.yxf.designpattern.observer.gama;
/**
* 天气对象
* @Description
* @author yxf
* @time 2018-8-21上午10:21:51
*/
public class Weather {
/**
* 温度
*/
public double temp;
/**
* 湿度
*/
public double humidity;
/**
* 压力
*/
public double pressure;
public Weather() {
}
public Weather(double temp, double humidity, double pressure) {
this.temp = temp;
this.humidity = humidity;
this.pressure = pressure;
}
public double getTemp() {
return temp;
}
public void setTemp(double temp) {
this.temp = temp;
}
public double getHumidity() {
return humidity;
}
public void setHumidity(double humidity) {
this.humidity = humidity;
}
public double getPressure() {
return pressure;
}
public void setPressure(double pressure) {
this.pressure = pressure;
}
}
3,测试入口
package com.yxf.designpattern.observer.gama;
/**
* 测试main
* @Description
* @author yxf
* @time 2018-8-21上午10:55:38
*/
public class MainTest {
public static void main(String[] args) {
//主题对象
WeatherData weatherData = new WeatherData();
//初始化温度\湿热\压力显示器
Observer tempDisplay = new TempDisplay();
Observer muggyDisplay = new MuggyDisplay();
Observer pressureDisplay = new PressureDisplay();
//注册观察者
weatherData.registerObserver(tempDisplay);
weatherData.registerObserver(muggyDisplay);
//设置推送状态
weatherData.setChange();//可用来控制什么时候才向观察者推送 --例如温度上升5度时才推送,位置可调整
System.out.println("====================第一次天气变化=================");
//天气变化
weatherData.changeMethod(new Weather(30, 15, 45));
System.out.println("====================第二次天气变化=================");
//移除天气显示器
weatherData.removeObserver(tempDisplay);
//注册压力显示器
weatherData.registerObserver(pressureDisplay);
//设置推送状态
weatherData.setChange();
//天气变化
weatherData.changeMethod(new Weather(24, 19.7, 52));
}
}
五,总结
在jdk中就自带的Observable类,但是由于它不是一个接口,可扩展性低.所以可以自己来写观察者模式,面向接口编程能够提高代码的可扩展性