设计模式之观察者模式

作者简介:大家好,我是smart哥,前中兴通讯、美团架构师,现某互联网公司CTO

联系qq:184480602,加我进群,大家一起学习,一起进步,一起对抗互联网寒冬

学习必须往深处挖,挖的越深,基础越扎实!

阶段1、深入多线程

阶段2、深入多线程设计模式

阶段3、深入juc源码解析


阶段4、深入jdk其余源码解析


阶段5、深入jvm源码解析

码哥源码部分

码哥讲源码-原理源码篇【2024年最新大厂关于线程池使用的场景题】

码哥讲源码【炸雷啦!炸雷啦!黄光头他终于跑路啦!】

码哥讲源码-【jvm课程前置知识及c/c++调试环境搭建】

​​​​​​码哥讲源码-原理源码篇【揭秘join方法的唤醒本质上决定于jvm的底层析构函数】

码哥源码-原理源码篇【Doug Lea为什么要将成员变量赋值给局部变量后再操作?】

码哥讲源码【你水不是你的错,但是你胡说八道就是你不对了!】

码哥讲源码【谁再说Spring不支持多线程事务,你给我抽他!】

终结B站没人能讲清楚红黑树的历史,不服等你来踢馆!

打脸系列【020-3小时讲解MESI协议和volatile之间的关系,那些将x86下的验证结果当作最终结果的水货们请闭嘴】  

观察者模式

定义

设计模式的一种。在此种模式中,一个目标对象管理所有相依于它的观察者对象,并且在它本身的状态改变时主动发出通知。这通常透过呼叫各观察者所提供的方法来实现。此种模式通常被用来实时事件处理系统。

( 引用维基百科 )

观察者模式(Observer)完美的将观察者和被观察的对象分离开。举个例子,用户界面可以作为一个观察者,业务数据是被观察者,用户界面观察业务数据的变化,发现数据变化后,就显示在界面上。面向对象设计的一个原则是:系统中的每个类将重点放在某一个功能上,而不是其他方面。一个对象只做一件事情,并且将他做好。观察者模式在模块之间划定了清晰的界限,提高了应用程序的可维护性和重用性。

观察者设计模式定义了对象间的一种一对多的组合关系,以便一个对象的状态发生变化时,所有依赖于它的对象都得到通知并自动刷新。

( 引用百度百科 )

白话文

出版者+订阅者=观察者模式。主题对象管理某些数据,当主题内的数据改变,就会通知观察者。观察者已经订阅(注册)主题以便在主题数据改变时能够收到更新。

类图

角色解析

  • Subject

    观察对象。定义了注册、删除、通知观察者接口。

  • ConcreteSubject

    观察对象具体实现类。

  • Observer

    所有潜在的观察者必须实现观察者接口。当主题状态改时它被调用。

  • ConcreteObserver

    具体的观察者可以是实现此接口的任意类。观察者必须注册到具体主题,以便接收更新。

实现

1. 定义主题接口

    /**
     * 主题接口
     * 注册、通知、移除
     */
    public interface Subject {
        /**
         * 注册观察者
         * @param o
         */
        void registerObserver(Observer o);
    
        /**
         * 移除观察者
         * @param o
         */
        void removeObserver(Observer o);
    
        /**
         * 当主题状态改变时,这个方法会被调用,以通知所有的观察者
         */
        void notifyObservers();
    }

2. 主题接口实现类

    /**
     * 主题接口实现类
     */
    public class WeatherData implements Subject{
        /**
         * 温度
         */
        private float temperature;
        /**
         * 湿度
         */
        private float humidity;
        /**
         * 压力
         */
        private float pressure;
    
        /**
         * 观察者列表
         */
        private List<Observer> observerList;
        
        public WeatherData() {
            observerList = new ArrayList<>();
        }
    
        /**
         * 注册观察者对象
         * @param o
         */
        @Override
        public void registerObserver(Observer o) {
            observerList.add(o);
        }
    
        /**
         * 解除观察者对象
         * @param o
         */
        @Override
        public void removeObserver(Observer o) {
            observerList.remove(o);
        }
    
        /**
         * 通知所有观察者
         */
        @Override
        public void notifyObservers() {
            for (Observer observer : observerList) {
                observer.update(temperature, humidity, pressure);
            }
        }
    
        /**
         * 当测试值改变时,调用通知方法
         */
        public void measurementsChange() {
            notifyObservers();
        }
    
        /**
         * 此方法模拟测量值改变
         */
        public void setMeasurements(float temperature, float humidity, float pressure) {
            this.temperature = temperature;
            this.humidity = humidity;
            this.pressure = pressure;
            measurementsChange();
        }
    }

3. 观察者接口

    /**
     * 定义观察者共同行为
     */
    public interface Observer {
        /**
         * 所有观察者必须实现接口。当主题值改变时,会调用此方法
         * @param temp
         * @param humidity
         * @param pressure
         */
        void update(float temp, float humidity, float pressure);
    }

4. 观察者具体实现类

    /**
     * 当前观察者实现类之一
     */
    public class CurrentConditionsDisplay implements Observer, DisplayElement{
        private float temperature;
        private float humidity;
        private Subject weatherData;
    
        public CurrentConditionsDisplay(Subject weatherData) {
            weatherData.registerObserver(this);
        }
    
        @Override
        public void display() {
            System.out.println("Current Condition: " + temperature + " F degrees and " + humidity + "% humidity.");
        }
    
        @Override
        public void update(float temp, float humidity, float pressure) {
            this.temperature = temp;
            this.humidity = humidity;
            display();
        }
    }
    /**
     * 当前观察者实现类之二
     */
    public class TempConditionDisplay implements Observer, DisplayElement{
        private float temp;
        public TempConditionDisplay(Subject subject) {
            subject.registerObserver(this);
        }
    
        @Override
        public void display() {
            System.out.println("Temp Condition Display,Current temp is " + temp);
        }
    
        @Override
        public void update(float temp, float humidity, float pressure) {
            this.temp = temp;
            display();
        }
    }

5. 其他接口及实现类

    /**
     * 布告板显示接口
     */
    public interface DisplayElement {
        void display();
    }

6. Main方法

    public class M {
        public static void main(String[] args) {
            // 创建主题类
            WeatherData weatherData = new WeatherData();
            // 创建观察者并把具体主题引入传入
            // 观察者之一
            CurrentConditionsDisplay currentConditionsDisplay = new CurrentConditionsDisplay(weatherData);
            // 观察者之二
            TempConditionDisplay tempConditionDisplay = new TempConditionDisplay(weatherData);
           
            // 温度变化
            weatherData.setMeasurements(1F, 3F, 4F);
        }
    }

总结

  1. 观察者模式提供了一种设计对象,让主题和观察者之间松耦合。主题只知道观察者实现了某个接口,并不需要知道观察者的具体类是谁、做了些什么或其他任何细节。
  2. 任何时候我们都可以增加新的观察者,因为主题唯一依赖的东西是一个实现Observer接口的对象列表。可以动态新增、删除、替换观察者,而其他观察者不受影响。只要它们之间的接口仍被遵守,我们就可以自由改变它们。松耦合的设计能让我们建立弹性的OO系统,能够应对变化,是因为对象之间的互相依赖降到了最低。
  3. 定义对象间的一种一对多的依赖关系。当一个对象状态发生改变时,所有依赖于它的对象都得到通知并被自动更新。
  4. 观察者模式可以实现两种动作。
  5. 注意: 不要依赖于观察者被通知的次序。
  6. Java有内置的观察者模式。包含最基本的Observer接口与Observable。但是Observable是一个而非接口,限制了它的使用和复用。自Java1.9废弃。
         * This class and the {@link Observer} interface have been deprecated.
         * The event model supported by {@code Observer} and {@code Observable}
         * is quite limited, the order of notifications delivered by
         * {@code Observable} is unspecified, and state changes are not in
         * one-for-one correspondence with notifications.
         * For a richer event model, consider using the
         * {@link java.beans} package.  For reliable and ordered
         * messaging among threads, consider using one of the concurrent data
         * structures in the {@link java.util.concurrent} package.
         * For reactive streams style programming, see the
         * {@link java.util.concurrent.Flow} API.
  1. 如果一下被观察者对象有很多直接和间接的观察者的话,将所有的观察者都通知会花费很多时间。
  2. 如果在观察者和观察目标之间有循环依赖的话,会触发它们之间的循环引用,进而导致系统崩溃。
  • 33
    点赞
  • 19
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
观察者模式是一种常用的设计模式,它定义了一种一对多的依赖关系,让多个观察者对象同时监听某一个主题对象,当主题对象状态发生变化时,它的所有观察者都会收到通知并更新自己的状态。 在C++中,观察者模式通常由一个抽象主题类和多个具体观察者类组成。抽象主题类中定义了添加、删除和通知观察者的接口,具体观察者类实现了更新自身状态的方法。 以下是一个简单的观察者模式示例: ```c++ #include <iostream> #include <vector> class Observer { public: virtual void update() = 0; }; class Subject { public: void attach(Observer* observer) { observers.push_back(observer); } void detach(Observer* observer) { for (auto it = observers.begin(); it != observers.end(); ++it) { if (*it == observer) { observers.erase(it); break; } } } void notify() { for (auto observer : observers) { observer->update(); } } private: std::vector<Observer*> observers; }; class ConcreteObserver1 : public Observer { public: void update() override { std::cout << "ConcreteObserver1 updated" << std::endl; } }; class ConcreteObserver2 : public Observer { public: void update() override { std::cout << "ConcreteObserver2 updated" << std::endl; } }; int main() { Subject subject; ConcreteObserver1 observer1; ConcreteObserver2 observer2; subject.attach(&observer1); subject.attach(&observer2); subject.notify(); subject.detach(&observer1); subject.notify(); return 0; } ``` 在上面的示例中,Subject类是抽象主题类,Observer类是抽象观察者类,ConcreteObserver1和ConcreteObserver2是具体观察者类。当Subject对象状态发生变化时,它会通知所有观察者更新自己的状态。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值