• C++实现观察者模式(包含源码)


    观察者模式

    一、基本概念

    观察者模式(又被称为模型(Model)-视图(View)模式)是软件设计模式的一种。在此种模式中,一个目标物件管理所有相依于它的观察者物件,并且在它本身的状态改变时主动发出通知。这通常透过呼叫各观察者所提供的方法来实现。

    二、实现方式

    观察者模式有很多实现方式,从根本上说,该模式必须包含两个角色:观察者和被观察者。

    比如在下面的代码表述中,发布作品的DY博主是被观察者,博主的粉丝是观察者 ,当DY博主(被观察者) 发生某种变化时 (状态改变),就会立即通知博主的粉丝 (观察者 )。

    三、角色

    1、抽象主题(Subject):

    它是一个抽象类,也是所有目标对象的父类。它用一个列表记录当前目标对象有哪些观察者对象,并提供增加(Add)、删除观察者对象(Delete)和通知观察者对象的接口。

    2、具体主题(ConcreteSubject):

    具体目标类,可以有多个不同的具体目标类,它们同时继承Subject类。一个目标对象就是某个具体目标类的对象,一个具体目标类负责定义它自身的事务逻辑,并在状态改变时通知它的所有观察者对象。

    3、抽象观察者(Observer):

    观察者类,它也是一个抽象类,是所有观察者对象的父类;它为所有的观察者对象都定义了一个名为show的方法(也叫成员函数)。当目标对象的状态改变时,它就是通过调用它的所有观察者对象的show方法来通知它们的。

    4、具体观察者(ConcreteObserver):

    具体观察者类,可以有多个不同的具体观察者类,它们同时继承Observer类。一个观察者对象就是某个具体观察者类的对象。每个具体观察者类都要重定义Observer类中定义的show方法,在该方法中实现它自己的任务逻辑,当它被通知的时候(目标对象调用它的show方法)就执行自己特有的任务。

    四、过程

    实现观察者模式有很多形式,比较直观的一种是使用一种“注册—通知—撤销注册”的形式。

    观察者

    (Observer)将自己注册到被观察对象(Subject)中,被观察对象将观察者存放在一个容器(Container)里。

    被观察对象

    被观察对象发生了某种变化,从容器中得到所有注册过的观察者,将变化通知观察者。

    撤销观察

    观察者告诉被观察者要撤销观察,被观察者从容器中将观察者去除。

    五、结构图

    img

    六、构建思路

    我们在前期已经了解了observer和subject的代表意义及用法,下面我们开始构思如何写代码

    先写出subject和observer类定义用法

    class Observer
    {
    public:
        virtual void update(){};
        virtual std::string getName()
        {
            return "";
        }
    };
    
    class Subject 
    {
    public:
        void Add(Observer *obs);
        void Delete(Observer *obs);
        void show();
        ~Subject();
    private:
        std::vectorobserver;
    };
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20

    Observer中的成员函数都是虚函数,不需要强调其作用,只需要了解虚函数的用法;

    Subject类的成员函数及变量:

    void Add(Observer *obs)---------------增加观察者

    void Delete(Observer *obs)------------删除观察者

    void show()-----------------------------------当被观察者状态发生改变时,及时通知观察者

    ~Subject()-------------------------------------析构函数,创建了许多观察者,最后需要析构删除

    std::vectorobserver-----存放观察者的信息,观察者存放到vector容器中

    具体主题(ConcreteSubject)和具体观察者(ConcreteObserver)的类定义

    class ConcreteSubject : public Subject
    {
    public:
        std::string getSubjectStatus();
        void   setSubjectStatus(ConcreteSubject * subject, const std::string &str);
    private:
        std::string subjectStatus;
    };
    
    class ConcreteObserver : public Observer
    {
    public:
        ConcreteObserver(ConcreteSubject *subject,std::string name);
        std::string getName();
        void update();
    private:
        std::string name;
        ConcreteSubject *subject;
        std::string observerStatus;
    };
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20

    具体主题(ConcreteSubject)类的成员函数及成员变量

    std::string getSubjectStatus() -------------------获得被观察者的状态

    void setSubjectStatus(ConcreteSubject * subject, const std::string &str) ------------设置被观察者的状态

    std::string subjectStatus---------------------------被观察者状态的变量

    具体主题(ConcreteObserver)类的成员函数及成员变量

    ConcreteObserver(ConcreteSubject *subject,std::string name)---------构造函数,初始化具体观察者

    std::string getName()-----------得到观察者的名字

    void update() ----------------------当被观察者状态改变时,提醒观察者

    std::string observerStatus-----观察者状态

    七、完整代码

    observer.h

    #include
    #include
    
    class Observer
    {
    public:
        virtual void update(){};
        virtual std::string getName()
        {
            return "";
        }
    };
    class Subject 
    {
    public:
        void Add(Observer *obs);
        void Delete(Observer *obs);
        void show();
        ~Subject();
    private:
        std::vectorobserver;
    };
    class ConcreteSubject : public Subject
    {
    public:
        std::string getSubjectStatus();
        void   setSubjectStatus(ConcreteSubject * subject, const std::string &str);
    private:
        std::string subjectStatus;
    };
    class ConcreteObserver : public Observer
    {
    public:
        ConcreteObserver(ConcreteSubject *subject,std::string name);
        std::string getName();
        void update();
    private:
        std::string name;
        ConcreteSubject *subject;
        std::string observerStatus;
    };
    
    • 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

    observer.cpp

    #include "observer.h"
    #include
    
    void Subject::Add(Observer *obs)
    {
        observer.push_back(obs);
    }
    void Subject::Delete(Observer *obs)
    {
        for(auto i = 0;i < observer.size();i++)
        {
            if(obs == observer[i])
            {
                observer.erase(observer.begin() + i);
            }
        }
    }
    void Subject::show()
    {
        auto it = observer.begin();  //vector::iterator
        while(it != observer.end())  
        {
            (*it)->update();        // it是指向observer元素的地址类似于observer.begin()。*it才相当于 observer[i]
            it++;
        }
    }
    Subject::~Subject()
    {
        std::cout<<"执行析构函数------"<getName()<show();
    }
    ConcreteObserver::ConcreteObserver(ConcreteSubject *subject,std::string name)
    {
        this->subject = subject;
        this->name = name;
    }
    std::string ConcreteObserver::getName()
    {
        return name;
    }
    void ConcreteObserver::update()
    {
        observerStatus = subject->getSubjectStatus();
        std::cout<<"您关注的DY博主更新动态了    粉丝: "<
    • 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

    main.cpp

    #include "observer.h"
    #include 
    int main()
    {
        ConcreteSubject *subject = new ConcreteSubject;
        subject->Add(new ConcreteObserver(subject,"TMG"));
        subject->Add(new ConcreteObserver(subject,"WYA"));
        subject->setSubjectStatus(subject,"在线");
        std::cout<
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    更多资料点击 GitHub 欢迎各位读者去Star

    ⭐学术交流群Q 754410389 持续更新中~~~

  • 相关阅读:
    jsp 上传文件及实体信息,ajax post 请求(formdata)报错400<======>前后端代码示例
    java毕业生设计医院药品管理系统计算机源码+系统+mysql+调试部署+lw
    C++11新特性 auto
    数据结构 栈和队列上
    基于检索增强的 GPT-3.5 的文本到 SQL 框架,具有样本感知提示和动态修订链。
    从 Elasticsearch 到 Apache Doris,统一日志检索与报表分析,360 企业安全浏览器的数据架构升级实践
    大二C++期末复习(自用)
    Spring Security 6.x 系列【66】认证篇之集成 LDAP 登录
    Lightroom“夏日清凉”调色思路
    NLP-了解BERT下游任务
  • 原文地址:https://blog.csdn.net/m0_63743577/article/details/132995093