• 【C++设计模式之观察者模式:行为型】分析及示例


    简介

    观察者模式(Observer Pattern)是一种行为型设计模式,它定义了一种一对多的依赖关系,使得当一个对象的状态发生变化时,所有依赖它的对象都能够自动收到通知并更新。

    描述

    观察者模式由两个核心件组成:主题(Subject)和观察者(Observer)。主题是一个可被观察的对象,它维护了一个观察者列表,可以动态地添加、删除和通知观察者。观察者是依赖于主题的对象,当主题发生变化时,观察者会自动更新自己的状态。

    原理

    观察者模式通过定义了主题和观察者之间的接口,使得主题和观察者可以彼此独立地进行交互。当主题的状态发生变化时,它会通知所有的观察者,而观察者会根据主题的通知进行相应的更新。

    类图

    在这里插入图片描述

    Subject:目标类,它是一个抽象类,也是所有目标对象的父类。它用一个列表记录当前目标对象有哪些观察者对象,并提供增加、删除观察者对象和通知观察者对象的接口。
    Observer:观察者类,它也是一个抽象类,是所有观察者对象的父类;它为所有的观察者对象都定义了一个名为update的方法(也叫成员函数)。当目标对象的状态改变时,它就是通过调用它的所有观察者对象的update方法来通知它们的。
    ConcreteSubject:具体目标类,可以有多个不同的具体目标类,它们同时继承Subject类。一个目标对象就是某个具体目标类的对象,一个具体目标类负责定义它自身的事务逻辑,并在状态改变时通知它的所有观察者对象。
    ConcreteObserver:具体观察者类,可以有多个不同的具体观察者类,它们同时继承Observer类。一个观察者对象就是某个具体观察者类的对象。每个具体观察者类都要重定义Observer类中定义的update方法,在该方法中实现它自己的任务逻辑,当它被通知的时候(目标对象调用它的update方法)就执行自己特有的任务。

    示例

    假设有一个天气预报系统,其中天气数据是主题,用户界面、手机App电视等是观察者。当天气数据更新时,所有的观察者都能够收到通知并更新自己的内容。

    C++示例代码如下:

    #include 
    #include 
    
    // 主题接口
    class Subject {
    public:
        virtual void attach(Observer* observer) = 0;
        virtual void detach(Observer* observer) = 0;
        virtual void notify() = 0;
    };
    
    // 观察者接口
    class Observer {
    public:
        virtual void update(const std::string& message) = 0;
    };
    
    // 具体主题
    class WeatherData : public Subject {
    public:
        void attach(Observer* observer) override {
            observers.push_back(observer);
        }
    
        void detach(Observer* observer) override {
            for (auto it = observers.begin(); it != observers.end(); ++it) {
                if (*it == observer) {
                    observers.erase(it);
                    break;
                }
            }
        }
    
        void notify() override {
            for (Observer* observer : observers) {
                observer->update(message);
            }
        }
    
        void setMessage(const std::string& message) {
            this->message = message;
            notify();
        }
    
    private:
        std::vector<Observer*> observers;
        std::string message;
    };
    
    // 具体观察者
    class UserInterface : public Observer {
    public:
        void update(const std::string& message override {
            std::cout << "User Interface: " << message << std::endl;
        }
    };
    
    class MobileApp : public Observer {
    public:
        void update(const std::string& message) override {
            std::cout << "Mobile App: " << message << std::endl;
        }
    };
    
    class TV : public Observer {
    public:
        void update(const std::string& message) override {
            std::cout << "TV: " << message << std::endl;
        }
    };
    
    // 使用示例
    int main() {
        WeatherData weatherData;
        UserInterface userInterface;
        MobileApp mobileApp;
        TV tv;
    
        weatherData.attach(&userInterface);
        weatherData.attach(&mobileApp);
        weatherData.attach(&tv);
    
        weatherData.setMessage("The is sunny.");
    
        weatherData.detach(&mobileApp);
    
        weatherData.setMessage("The weather is rainy");
        return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89

    输出结果

    User Interface: The weather is sunny.
    Mobile App: The weather is sunny.
    TV: The is sunny.
    User Interface: The weather is rainy.
    TV: The weather is rainy.
    
    • 1
    • 2
    • 3
    • 4
    • 5

    解释

    在上述示例中,主题接口(Subject)定义了操作观察者的方法,包括添加观察者、删除观察者和通知观察者。
    具体主题(WeatherData)实现了主题接口,并维护了一个观察者列表。
    观察者接口(Observer)定义了观察者的更新方法,具体观察者(UserInterface、MobileApp、TV)实现了观察者接口,并根据主题的通知进行相应的更新。

    在示例中,创建了一个天气数据对象(WeatherData)作为主题,然后创建了三个观察者(UserInterface、MobileApp、TV)。将观察者添加到天气数据对象的观察者列表中,然后模拟天气数据发生变化,通过调用主题的notify方法通知所有的观察者。察者接收到通知后,会调用自己的update方法进行相应的更新操作。

    结论

    结论观察者模式通过定义了一种一对多的依赖关系,使得主题和观察者之间能够彼此独立地进行交互。它实现了对象间的解耦,当一个对象的状态发生变化时,所有依赖它的对象都能够自动收到通知并进行相的更新。

    观察者模式适用场景:

    • 当一个对象的改变需要同时通知其他对象,并且不道具体有多少个对象需要通知时,可以使用观察者模式实现松散的耦合。
    • 当一个对象需要将自己的改变通知给其他对象,但是又希望避免耦合时,可以使用观察者模式。

    观察者模式常见的应用场景包括事件驱动系统、GUI界面组件、消息队列系统等。

  • 相关阅读:
    Unity 动态修改自定义字体(Text)颜色
    Allure的安装
    Typora 窗口总数跳动问题
    输出心形图案
    ARM汇编之程序状态寄存器传输指令
    JVM堆内存释放不及时问题
    Java安全—CommonsCollections7
    IT行业就业方向如何选择?
    【cmake】cmake生成Visual Studio工程后的INSTALL项目使用
    (前端)「状态」设计模式在项目开发中的应用
  • 原文地址:https://blog.csdn.net/MrHHHHHH/article/details/133618233