观察者模式

概述

观察者模式是对象间多对一依赖的一种设计方案,被依赖的对象为Subject,依赖的对象为Observer,Subject通知bserver变化。也就是开闭原则

例子

需求
  1. 气象站可以每天测量到温度,湿度,气压等以公告的形式发布出去。
  2. 需要设计开放型api,便于其他第三方也可以接入气象台获取数据
  3. 提供温度,湿度,气压的接口
  4. 测量数据更新时,实时通知第三方

传统思维

创建一个WeatherData模式气象台的数据,该类维护一个观察者对象,对对象进行操作

/*核心类
* 1、含有最新的天气情况信息
* 2、含有CurrentConditions对象
* 3、当数据有更新时,就主动的调用 CurrentConditions对象update方法,这样接入方就可以看到最新的消息
*
* 缺点:无法在运行时动态添加第三方,添加第三方非常麻烦,违反了开闭原则
* */
public class WeatherData {
    private float temperatrue;
    private float pressure;
    private float humidity;
    private CurrentConditions currentConditions;//维护的观察者对象
    public WeatherData(CurrentConditions currentConditions){
        this.currentConditions = currentConditions;
    }
    public float getTemperatrue(){
        return temperatrue;
    }
    public float getPressure(){
        return pressure;
    }
    public float getHumidity(){
        return humidity;
    }
    public void dataChange(){
        currentConditions.update(temperatrue,pressure,humidity);
    }
    //数据更新时调用setData
    public void setData(float temperatrue,float pressure,float humidity){
        this.temperatrue = temperatrue;
        this.pressure = pressure;
        this.humidity = humidity;
        //推送消息给接受方
        dataChange();
    }
}

创建观察者对象

public class CurrentConditions {
    //模拟数据
    private float temperature;//温度
    private float pressure;//压强
    private float humidity;//湿度
    //提供数据更新接口,便于气象台管理数据更新
    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+"***");
    }
}

客户端代码

public class Client {
    public static void main(String[] args) {
        //创建接入方currentConditions
        CurrentConditions currentConditions = new CurrentConditions();
        //创建WeatherData,并将CurrentCondition传递到WeatherData中
        WeatherData weatherData = new WeatherData(currentConditions);
        //更新天气信息
        weatherData.setData(30,140,40);
        try {
            Thread.sleep(3000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        //更新信息
        System.out.println("============天气更新=============");
        weatherData.setData(45,150,23);

    }
}

传统模式的缺点:气象台weatherData只维护对应的观察者对象,当添加新的第三方接口调用的时候,维护比较困难,需要修改WeatherData中的代码,无法做到实时动态跟新。

观察者模式改进

我们通过实现接口的方式统一管理观察者,在weatherData中维护一个该接口的观察者列表,当数据更新的时候,循环列表统一通知第三方接口。在weatherData中提供注册和删除接口,实现动态添加观察者。
Subject接口设计

//import java.util.Observer;
//接口,让WeatherData来实现
public interface Subject {
    public void registerObver(Observer o);
    public void removeObver(Observer o);
    public void notifyObservers();
}

WatherData实现类

	/*核心类
* 1、含有最新的天气情况信息
* 2、含有观察者集合,使用ArrayList管理
* 3、当数据有更新时,就主动的调用 ArrayList对象update方法,通知接入方获取最新的消息
*
* 缺点:无法在运行时动态添加第三方,添加第三方非常麻烦,违反了开闭原则
* */
public class WeatherData implements Subject{
    private float temperatrue;
    private float pressure;
    private float humidity;
    private ArrayList<Observer> observers;//观察者对象列表
    public WeatherData(){
        observers = new ArrayList<Observer>();
    }
    public float getTemperatrue(){
        return temperatrue;
    }
    public float getPressure(){
        return pressure;
    }
    public float getHumidity(){
        return humidity;
    }
    public void dataChange(){
        //currentConditions.update(temperatrue,pressure,humidity);
        notifyObservers();//调用通知所有消息到第三方接口
    }
    //数据更新时调用setData
    public void setData(float temperatrue,float pressure,float humidity){
        this.temperatrue = temperatrue;
        this.pressure = pressure;
        this.humidity = humidity;
        //推送消息给接受方
        dataChange();
    }
    //添加一个观察者
    @Override
    public void registerObver(Observer o) {
        observers.add(o);
    }
    //移除一个观察者
    @Override
    public void removeObver(Observer o) {
        observers.remove(o);
    }
    //遍历所有观察者,并通知
    @Override
    public void notifyObservers() {
        for (Observer ob: observers
             ) {
            ob.update(getTemperatrue(),getPressure(),getHumidity());
        }
    }
}

观察者类接口,所有观察者都必须继承该接口,WeatherDate聚合了该接口

//观察者接口,由观察者实现
public interface Observer {
    public void update(float temperture,float pressure,float humidity);
}

观察者实现类

public class CurrentConditions implements Observer{
    //模拟数据
    private float temperature;//温度
    private float pressure;//压强
    private float humidity;//湿度
    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("** currentcondition温度为"+temperature+"***");
        System.out.println("**currentcondition的压强为"+pressure+"***");
        System.out.println("**currentcondition的湿度为"+humidity+"***");
    }
}
public class Baidu  implements Observer{
    //模拟数据
    private float temperature;//温度
    private float pressure;//压强
    private float humidity;//湿度
    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("** baidu温度为"+temperature+"***");
        System.out.println("**baidu的压强为"+pressure+"***");
        System.out.println("**baidu的湿度为"+humidity+"***");
    }
}

在客户端进行观察者的注册和更改数据

public class Client {
    public static void main(String[] arg) {
        //创建一个Weather
        Subject weatherData = new WeatherData();
        //创建观察者
        CurrentConditions currentConditions = new CurrentConditions();
        //创建另一个观察者
        Baidu baidu = new Baidu();
        //注册到WeatherData
        weatherData.registerObver(currentConditions);
        weatherData.registerObver(baidu);
        //测试
        System.out.println("通知各个注册的观察者。看看信息");
        ((WeatherData) weatherData).setData(10f,100f,30.3f);
        //取消注册
        weatherData.removeObver(currentConditions);

        //再次测试
        System.out.println("通知各个注册的观察者。看看信息");
        ((WeatherData) weatherData).setData(20f,123f,12.3f);
    }
}

使用观察者模式,我们将观察者抽象成接口的实现,方便管理,这样当我们需要添加新的第三方接口调用时,只需要继承Observer接口,并在客户端进行注册便可,不需要修改WeatherData代码。这符合开闭原则,提高了项目的扩展性。

观察者模式在JDK中的实现

Observable类根据观察者模式,与以上的例子类似。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值