一、观察者模式介绍
- 观察者模式:对象之间多对一的一种设计方案,被依赖的对象subject,依赖的对象为Observer,Subject通知Observer变化。
- 观察者模式好处
1)观察者模式设计后,会以集合的方式来管理用户,包括注册,移除和通知。
2)增加观察查者,不需要去修改核心类,不会修改代码,遵循了OCP原则。
二、观察者模式应用
- 应用实例
天气预报项目需求,具体要求如下:
1)气象站可以将每天测量的温度,湿度,气压等等以公告的形式发布出去(比如发布到自己的网站或者第三方)。
2)需要设计开放型API,便于其他第三方也能接入气象站获取数据。
3)提供温度、气压和湿度的接口。
4)测量数据更新时,要能实时的通知给第三方。 - 类图
- 代码
1)观察者接口
//观察者接口,有观察者实现
public interface Observer {
public void update(float temperature,float pressure,float humidity);
}
2)具体观察者
public class CurrentConditions implements Observer{
//温度,气压,湿度
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;
this.display();
}
//显示
public void display(){
System.out.println("***Today mTemperature:"+temperature+"***");
System.out.println("***Today mTemperature:"+pressure+"***");
System.out.println("***Today mTemperature:"+humidity+"***");
}
}
public class BaiduSite implements Observer{
//温度,气压,湿度
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;
this.display();
}
//显示
public void display(){
System.out.println("======百度网站======");
System.out.println("***百度网站 气温:"+temperature+"***");
System.out.println("***百度网站 气压:"+pressure+"***");
System.out.println("***百度网站 湿度:"+humidity+"***");
}
}
3)通知者接口
//接口,让WeatherData来实现
public interface Subject {
public void rejecterObserver(Observer o);
public void removeObserver(Observer o);
public void notifyObservers();
}
4)通知实现者
/**
* 类是核心
* 1.包含最新的天气情况信息
* 2.含有观察者集合,使用ArrayList管理
* 3.当数据有更新时,就主动的调用ArrayList,通知所有的(接入方),使看到最新的消息
*/
public class WeatherData implements Subject{
private float temperature;
private float pressure;
private float humidity;
//观察者集合
private ArrayList<Observer> observers;
public WeatherData(){
observers = new ArrayList<Observer>();
}
public float getTemperature() {
return temperature;
}
public void setTemperature(float temperature) {
this.temperature = temperature;
}
public float getPressure() {
return pressure;
}
public void setPressure(float pressure) {
this.pressure = pressure;
}
public float getHumidity() {
return humidity;
}
public void setHumidity(float humidity) {
this.humidity = humidity;
}
public ArrayList<Observer> getObservers() {
return observers;
}
public void setObservers(ArrayList<Observer> observers) {
this.observers = observers;
}
public void dataChange(){
notifyObservers();
}
//当数据有更新时,就调用setData
public void setData(float temperature,float pressure,float humidity){
this.temperature = temperature;
this.pressure = pressure;
this.humidity = humidity;
//调用dataChange,将最新的消息推送给接入方currentConditions
dataChange();
}
//注册一个观察者
public void rejecterObserver(Observer o) {
observers.add(o);
}
//移除一个观察者
public void removeObserver(Observer o) {
if(observers.contains(o)){
observers.remove(o);
}
}
//遍历所有的观察者,并通知
public void notifyObservers() {
for(int i = 0; i < observers.size(); i++){
observers.get(i).update(this.temperature,this.pressure,this.humidity);
}
}
}
5)客户端类
public class Client {
public static void main(String[] args) {
//创建一个weatherData
WeatherData weatherData = new WeatherData();
//创建观察者
CurrentConditions currentConditions = new CurrentConditions();
BaiduSite baiduSite = new BaiduSite();
//注册到weatherData
weatherData.rejecterObserver(currentConditions);
weatherData.rejecterObserver(baiduSite);
//测试
System.out.println("通知各个注册的观察者,看看信息");
weatherData.setData(10f,100f,30f);
}
}