• Observer 模式


    💡问题引入

    假设有一个在线商店系统,用户可以订阅商品的库存通知。当某个商品的库存数量发生变化时,系统会自动发送通知给所有订阅了该商品的用户。设计一个使用观察者模式的系统来实现这个功能。

    💡概念

    定义对象间的一种一对多(变化)的依赖关系,以便当一个对象(Subject)的状态发生改变时,所有依赖它的对象都得到通知并自动更新

    💡例子

    • 观察者模式实例
    #include 
    #include 
    #include 
    
    // 观察者接口
    class Observer {
    public:
        virtual void update(const std::string& message) = 0;
    };
    
    // 被观察者类
    class Subject {
    private:
        std::list<Observer*> observers;   // 观察者列表
        std::string message;                // 存储消息
    
    public:
        // 添加观察者
        void attach(Observer* observer) {
            observers.push_back(observer);
        }
    
        // 移除观察者
        void detach(Observer* observer){
            m_ObsList.remove(observer);
        }
        
        // 通知观察者
        void notify() {
            for (auto observer : observers) {
                observer->update(message);
            }
        }
    
        // 设置消息并触发通知
        void setMessage(const std::string& newMessage) {
            message = newMessage;
            notify();
        }
    };
    
    // 具体观察者类
    class ConcreteObserver : public Observer {
    private:
        std::string name;   // 观察者名称
    
    public:
        // 构造函数
        ConcreteObserver(const std::string& observerName) : name(observerName) {}
    
        // 实现观察者接口的update方法
        void update(const std::string& message) {
            std::cout << name << " received the message: " << message << std::endl;
        }
    };
    
    int main() {
        // 创建主题
        Subject subject;
    
        // 创建观察者
        ConcreteObserver observer1("Observer 1");
        ConcreteObserver observer2("Observer 2");
        ConcreteObserver observer3("Observer 3");
    
        // 将观察者添加到主题中
        subject.attach(&observer1);
        subject.attach(&observer2);
        subject.attach(&observer3);
    
        // 设置主题的消息,触发通知
        subject.setMessage("Hello, observers!");
    
        // 将观察者从主题中删除
        subject.detach(&observer2);
    
        // 再次设置主题的消息,触发通知,此时observer2不会收到消息
        subject.setMessage("Goodbye!");
    
        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

    观察者模式结构类图
    在这里插入图片描述

    问题分析
    ➢在软件构建过程中,我们需要为某些对象建立一种“通知依赖关系”一一个对象(目标对象)的状态发生改变,所有的依赖对
    象(观察者对象)都将得到通知。如果这样的依赖关系过于紧密,将使软件不能很好地抵御变化。
    ➢使用面向对象技术,可以将这种依赖关系弱化,并形成一种稳定的依赖关系。从而实现软件体系结构的松耦合。

    • 问题引入的实现代码
    // 观察者接口
    class Observer {
    public:
        virtual void update(const std::string& productId, int stockCount) = 0;
    };
    
    // 被观察者类(商品)
    class Product {
    private:
        std::string productId;
        int stockCount;
        std::list<Observer*> observers;
    
    public:
        Product(const std::string& id) : productId(id), stockCount(0) {}
    
        // 添加观察者
        void attach(Observer* observer) {
            observers.push_back(observer);
        }
    
        // 移除观察者
        void detach(Observer* observer) {
            observers.remove(observer);
        }
    
        // 通知观察者
        void notify() {
            for (auto observer : observers) {
                observer->update(productId, stockCount);
            }
        }
    
        // 设置库存数量并触发通知
        void setStockCount(int count) {
            stockCount = count;
            notify();
        }
    };
    
    // 具体观察者类(用户)
    class User : public Observer {
    private:
        std::string userId;
    
    public:
        User(const std::string& id) : userId(id) {}
    
        // 实现观察者接口的update方法
        void update(const std::string& productId, int stockCount) {
            std::cout << "User " << userId << ": Product " << productId << " has a new stock count of " << stockCount << std::endl;
        }
    };
    
    int main() {
        // 创建商品
        Product product1("12345");
        Product product2("67890");
    
        // 创建用户
        User user1("Alice");
        User user2("Bob");
    
        // 将用户添加为商品的观察者
        product1.attach(&user1);
        product1.attach(&user2);
        product2.attach(&user1);
    
        // 设置商品的库存数量,触发通知
        product1.setStockCount(10);
        product2.setStockCount(5);
    
        // 将某个用户从商品的观察者列表中移除
        product1.detach(&user2);
    
        // 再次设置商品的库存数量,触发通知
        product1.setStockCount(15);
    
        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

    运行结果如图
    在这里插入图片描述

    💡总结

    ➢使用面向对象的抽象, Observer模式使得我们可以独立地改变目标与观察者,从而使二者之间的依赖关系达致松耦合。
    ➢目标发送通知时,无需指定观察者,通知(可以携带通知信息作为参数)会自动传播。
    ➢观察者自己决定是否需要订阅通知,目标对象对此一无所知。
    ➢Observer模式是基于事件的UI框架中非常常用的设计模式,也是MVC模式的一一个重要组成部分。

  • 相关阅读:
    html+css如何实现鼠标移入按钮显示图片
    Kotlin okhttp3 HttpClient
    leetCode 674. 最长连续递增序列 动态规划 / 贪心策略
    牛客网之SQL非技术快速入门(7)-字符串截取、切割、删除、替换
    Netty入门——组件(Channel)二
    【JavaScript】WebAPI详解
    MATLAB算法实战应用案例精讲-【图像处理】机器视觉(最终篇)
    图像识别-YOLO V8安装部署-window-CPU-Pycharm
    深入理解 Hive UDAF
    开源的价值观与文化的传递
  • 原文地址:https://blog.csdn.net/qq_56166591/article/details/135505747