Head First 设计模式总结(二)观察者模式

本文对《Head First 设计模式》中的观察者模式进行了概括和总结

观察者模式——在对象之间定义一对多的依赖,这样一来,当一个对象改变状态,依赖他的对象都会收到通知,并自动更新。

问题描述

要求公司建立一个 气象数据站 (WeatherData对象),使之能从 气象观测站 (WeatherStation对象)获取气象数据(温度temperature,湿度humidity,气压值pressure)。

并要求公司开发一个应用,使其包含三个天气显示板:目前状况、气象统计、天气预测,这三个对象都获取了来自WeatherData的三个气象数据,但是对这些数据的处理方式不一样。要求显示板的显示数据根据WeatherData传过来的气象数据实时变化。
下图就是将气象数据传给了“目前状况”这个展示板。
在这里插入图片描述

下面进入正题。

观察者模式的思想

主题(Subject)+观察者(Observer)=观察者模式

在这里插入图片描述

下图是Subject和Observer之间的关系
在这里插入图片描述
观察者模式提供了一种对象设计,让主题和观察者之间松耦合
关于观察者的一切,主题只知道观察者实现了某个接口(Observer接口),主题只需要知道这个观察者 注册与否 (是否需要定期向它提供消息),如果注册了,就定期发送消息给他。主题不需要知道观察者本身具体是谁、做了什么以及其他细节。

当新的观察者注册时,不用改主题代码,只需将通知的消息给这个新来的观察者发一份就行了,观察者不在乎别的,它只会将相同消息发送给所有实现了Observer接口的具体观察者对象,它一视同仁

以下是本例利用观察者模式的结构图

在这里插入图片描述
下面给出本例WeatherData类的实现代码

class WeatherData implements Subject {
    private float temperature;
    private float humidity;
    private float pressure;
    private ArrayList observers;
    public WeatherData(){
        List<Observer> observers = new ArrayList<Observer>();
    }
    @Override
    public void registerObserver(Observer o) {  //注册为观察者
            observers.add(o);
    }

    @Override
    public void removeObserver(Observer o) {  //注销,不再为观察者
        int i = observers.indexOf(o);
        if(i>=0){
            observers.remove(o);
        }
    }
    @Override
    public void notifyObservers() {       //通知各个观察者
        for(int i = 0;i<observers.size();i++){  //遍历观察者List,挨个调用每个观察者的update()方法,实现通知
            Observer observer = (Observer) observers.get(i);
            observer.update(temperature,humidity,pressure);
        }
    }
    public void measurementsChanged(){
        notifyObservers();
    }
    public void setMeasurements(float temp,float humidity,float pressure){
        this.temperature = temp;
        this.humidity = humidity;
        this.pressure = pressure;
        measurementsChanged();
        WeatherStation.times++;
    }
}

以下是其中一个具体观察者的代码实现:

class CurrentConditionDisplay implements Observer{
    private float temperature;
    private float humidity;
    private Subject weatherData;
    public CurrentConditionDisplay(Subject weatherData){  //通过观察者的构造器将weatherData传进来,并将该观察者注册
        this.weatherData = weatherData;
        weatherData.registerObserver(this);
        //weatherData.removeObserver(this);
    }
    public void display() {
        System.out.println("current condition: "+temperature+"F degrees and"+humidity+"% humidity");
    }
    @Override
    public void update(float temp, float humidity, float pressure) { //该方法由weatherData的notifyObserver()方法触发
        this.temperature = temp;
        this.humidity = humidity;
        display();
    }
}

总结

该设计模式的关键在于:如何将具体主题(WeatherData)和具体观察者(Concret Observer)相互联系起来

解析:

1、观察者们利用weatherData对象去注册和注销

registerObserver()方法和removeObserver()方法都在weatherData对象中,因此具体观察者的注册必须通过weatherData对象来完成,但是是否注册还是由具体观察者它自己决定,所以得将weatherData对象传到具体观察者内部,显然直接将weatherData对象传入具体观察者的构造器最直观,因为当new出具体观察者对象的时刻就能决定是否注册为观察者了。

2、weatherData利用观察者们的对象才能调用它们的update()方法

由于有多个观察者,因此可用一个Observer类型的List来存放注册了的Observer,一旦某个Observer注册成功,该观察者的对象就传到了List中,因此weatherData可以访问所有注册过的观察者。这样的目的在这里很明确,一旦新数据到来,weatherData对象就调用notifyObserver()方法,进而利用List中的所有观察者对象去调用它们各自的update()方法。

本设计模式中的一个设计原则是:为交互对象之间的松耦合而努力

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值