设计模式之观察者模式

22 篇文章 0 订阅
21 篇文章 2 订阅
本文介绍了观察者模式,一种行为型设计模式,用于建立对象间的多对一依赖关系。当被观察者状态变化时,所有依赖的观察者都会收到通知并自动更新。文章详细阐述了观察者模式的四个角色:抽象被观察者、具体被观察者、抽象观察者和具体观察者,并通过气象中心和天气应用的实例进行说明。最后,提到了使用观察者模式能遵循开闭原则,方便添加新的观察者。
摘要由CSDN通过智能技术生成

观察者模式

观察者模式(Observer Pattern)也叫发布-订阅(Publish/Subscribe)模式,是属于行为型模式。观察者模式定义了一种对象间多对一的依赖关系,使得当被观察者状态发生改变时,其相关依赖对象皆得到通知并被自动更新。

观察者模式的四个角色

  • Subject(抽象被观察者角色): 这是一个抽象类或接口,定义了对观察者集合的操作,例如注册观察者、删除观察者和通知更新观察者信息等。
  • ConcreteSubject(具体被观察者角色): 具体观察者角色有自己的属性和方法,并实现了抽象被观察者的方法。它定义了一个观察者集合,通过一些方法对观察者和观察者集合进行操作。
  • Observer(抽象观察者角色): 抽象观察者通常是一个抽象类或接口,它定义了一个更新方法,当被观察者状态改变时,通过此方法更新自己的状态。
  • ConcreteObserver(具体观察者角色): 具体观察者实现了抽象观察者的方法,当被观察者状态发生改变,通过update()方法来更新自己的状态。
image-20201003212327148

举一个栗子

假设有一个气象中心负责观察天气信息,有温度、气压和湿度等。然后有一些天气软件,通过使用气象中心提供的数据放到自己的软件中作为展示天气的功能,当气象中心的数据发生变化时,气象中心又把这些更新后的数据推动给这些应用软件,来更新各个软件中的天气数据。

Subject:抽象被观察者

这个接口定义了三个方法,方法的作用在注释用可以看到。

package cn.personalweb.observer;

public interface Subject {
    /**
     * 注册观察者, 将观察者添加到观察者集合里
     * @param observer 观察者
     */
    public void registerObserver(Observer observer);

    /**
     * 通过观察者对象, 从集合中删除此观察者
     * @param observer 观察者
     */
    public void removeObserver(Observer observer);

    /**
     * 通知在集合中的所有观察者
     */
    public void notifyObservers();
}

Observer:抽象观察者

定义了一个update()方法,用于更新自己的状态

package cn.personalweb.observer;

public interface Observer {

    /**
     * 更新观察者数据
     * @param temperature 温度
     * @param pressure 气压
     * @param humidity 湿度
     */
    public void update(float temperature, float pressure, float humidity);
}

WeatherData:具体被观察者

这里的被观察者是天气数据,观察者来观察天气数据。当天气数据发生改变是,也就是setData()方法执行时,会调用notifyObservers()方法来改变每一个观察者的数据,也就是将最新的数据修改到观察者。

package cn.personalweb.observer;

import java.util.ArrayList;

public class WeatherData implements Subject {

    /**
     * 温度
     */
    private float temperature;
    /**
     * 气压
     */
    private float pressure;
    /**
     * 湿度
     */
    private float humidity;
    /**
     * 观察者集合
     */
    private ArrayList<Observer> observers;

    public WeatherData() {
        this.observers = new ArrayList<Observer>();
    }


    /**
     * 设置数据
     * @param temperature 温度
     * @param pressure 气压
     * @param humidity 湿度
     */
    public void setData(float temperature, float pressure, float humidity) {
        this.temperature = temperature;
        this.pressure = pressure;
        this.humidity = humidity;

        // 当数据改变后, 调用通知所有观察者
        notifyObservers();
    }

    @Override
    public void registerObserver(Observer observer) {
        observers.add(observer);
    }

    @Override
    public void removeObserver(Observer observer) {
        observers.remove(observer);
    }

    @Override
    public void notifyObservers() {
        for (Observer observer : observers) {
            observer.update(this.temperature, this.pressure, this.humidity);
        }
    }
}

BaiduObserver:具体百度观察者

BaiduObserver表示一个具体的观察者,也就是一个具体的软件平台,这些具体的观察者观察天气中心。当天气中心,也就是天气数据发生改变时,会将修改后的数据推送到具体的观察者上。

package cn.personalweb.observer;

public class BaiduObserver implements Observer{
    private float temperature;
    private float pressure;
    private float humidity;

    @Override
    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);
    }
}

XiaoMiObserver:具体小米观察者

功能同百度观察者。

package cn.personalweb.observer;

public class XiaoMiObserver implements Observer{

    private float temperature;
    private float pressure;
    private float humidity;

    @Override
    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);
    }
}

Client:客户端

package cn.personalweb.observer;

public class Client {
    public static void main(String[] args) {
        // 创建WeatherData
        WeatherData weatherData = new WeatherData();

        // 创建观察者
        XiaoMiObserver xiaoMiObserver = new XiaoMiObserver();
        BaiduObserver baiduObserver = new BaiduObserver();

        // 将观察者注册到 WeatherData
        weatherData.registerObserver(xiaoMiObserver);
        weatherData.registerObserver(baiduObserver);

        //设置天气, 并通知观察者
        weatherData.setData(30f, 100, 20f);

        System.out.println("----------");
        // 删除观察者
        weatherData.removeObserver(xiaoMiObserver);
        weatherData.setData(20f, 110, 22f);

    }
}

输出结果

小米天气的温度是:30.0
小米天气的气压是:100.0
小米天气的湿度是:20.0
百度天气的温度是:30.0
百度天气的气压是:100.0
百度天气的湿度是:20.0
----------
百度天气的温度是:20.0
百度天气的气压是:110.0
百度天气的湿度是:22.0

使用观察者模式的优点

观察者模式设计后,会以集合的方式来管理用户(Observer),包括注册,移除和通知。这样,我们增加观察者(这里可以理解成一个新的公告板),就不需要去修改核心类 WeatherData 不会修改代码, 遵守了 ocp


参考资料:

尚硅谷 Java 设计模式课程笔记。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值