• 【设计模式】观察者模式及函数式编程的替代C++


    本文介绍观察者模式以及使用函数式编程替代简单的策略模式。

    观察者模式

    观察者模式是一种行为型设计模式,它定义了一种一对多的依赖关系,当一个对象的状态发生改变时,其所有依赖者都会收到通知并自动更新。

    当对象间存在一对多关系时,则使用观察者模式(Observer
    Pattern)。比如,当一个对象被修改时,则会自动通知依赖它的对象。观察者模式属于行为型模式。

    简单来说,观察者模式需要多个对象观察同一个对象,被观察的对象称为Subject(主题),Subject需要完成观察者的注册(attach),注销(detach)和通知(notify)三个操作。
    观察者模式,图片来自菜鸟教程
    首先实现一个公共的Observer父类,这个父类只有一个纯虚函数,用来更新自身状态:

    struct Observer
    {
    public:
        virtual void update() = 0;
    };
    
    • 1
    • 2
    • 3
    • 4
    • 5

    两个具体的类,实现 update 函数:

    struct ConcreteObserver : Observer
    {
    public:
        void update() override
        {
            std::cout << "State updated!" << std::endl;
        }
    };
    
    struct ConcreteObserver2 : Observer
    {
    public:
        void update() override
        {
            std::cout << "State updated! 2" << std::endl;
        }
    };
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17

    接下来实现被观察者公共类,包含添加、删除、通知所有观察者三个接口:

    struct Subject
    {
    public:
        virtual void attach(Observer *observer) = 0;
        virtual void detach(Observer *observer) = 0;
        virtual void notify() = 0;
    };
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    具体的被观察者类,实现这三个接口:

    struct ConcreteSubject : 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 (auto &observer : observers)
            {
                observer->update();
            }
        }
    
    private:
        std::vector<Observer *> observers;
    };
    
    • 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

    测试代码如下:

    int main()
    {
        ConcreteSubject subject;
        ConcreteObserver observer1;
        ConcreteObserver2 observer2;
    
        subject.attach(&observer1);
        subject.attach(&observer2);
    
        subject.notify();
    
        subject.detach(&observer1);
    
        subject.notify();
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15

    结果

    函数式编程下的观察者模式

    首先需要介绍下C语言的函数指针。所谓函数指针即定义一个指向函数的指针变量,格式如下:

    typedef void (*Callback)();
    
    • 1

    这样就定义了一个变量名为Callback的指针变量,指向一个参数为void,返回值也为void的函数。我们用这种指针变量,就能将整个观察者类改成函数。

    两个观察者函数:

    void callback1()
    {
        std::cout << "State updated!" << std::endl;
    }
    
    void callback2()
    {
        std::cout << "State updated! 2" << std::endl;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    被观察的类。原先调用观察者类的地方全部改为函数调用:

    struct ConcreteSubject
    {
    public:
        void attach(Callback callback)
        {
            observers.push_back(callback);
        }
    
        void detach(Callback callback)
        {
            for (auto it = observers.begin(); it != observers.end(); it++)
            {
                if (*it == callback)
                {
                    observers.erase(it);
                    break;
                }
            }
        }
    
        void notify()
        {
            for (auto &observer : observers)
            {
                observer();
            }
        }
    
    private:
        std::vector<Callback> observers;
    };
    
    • 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

    观察者模式与回调

    我给函数指针起名为Callback。事实上,当只有一个观察者的时候,观察者模式的机制就等同于回调模式。因此可以认为,回调模式是一种特殊的观察者模式。

  • 相关阅读:
    语法练习:front3
    负载均衡Ribbon和Feign的使用与区别
    vim的使用笔记
    复习 --- select并发服务器
    JAVA后端开发面试基础知识(十)——设计模式
    JZ49 [剑指 Offer 49] 丑数
    (四) 一文搞懂 JMM - 内存模型
    python 面向对象
    2562. 找出数组的串联值
    515万新作者投身电商事业,抖音电商将投入更多资源扶持作者长期发展
  • 原文地址:https://blog.csdn.net/qq_37387199/article/details/136434313