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::vector<Observer *>observer;
};

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

Subject类的成员函数及变量:

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

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

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

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

std::vector<Observer *>observer-----存放观察者的信息,观察者存放到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;
};

具体主题(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<iostream>
#include<vector>

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::vector<Observer *>observer;
};
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;
};

observer.cpp

#include "observer.h"
#include<iostream>

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<Observer*>::iterator
    while(it != observer.end())  
    {
        (*it)->update();        // it是指向observer元素的地址类似于observer.begin()。*it才相当于 observer[i]
        it++;
    }
}
Subject::~Subject()
{
    std::cout<<"执行析构函数------"<<std::endl;
    auto it = observer.begin();
    while(it != observer.end())
    {
        std::cout<<"已经删除:"<<(*it)->getName()<<std::endl;
        delete *it;
        it++;
    }
    observer.clear();
}
std::string ConcreteSubject::getSubjectStatus()
{
    return subjectStatus;
}
void ConcreteSubject::setSubjectStatus(ConcreteSubject * subject,const std::string &str)
{
    subjectStatus = str;
    subject->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博主更新动态了    粉丝: "<<name<<"用户状态: "<<observerStatus<<std::endl;
}

main.cpp

#include "observer.h"
#include <iostream>
int main()
{
    ConcreteSubject *subject = new ConcreteSubject;
    subject->Add(new ConcreteObserver(subject,"TMG"));
    subject->Add(new ConcreteObserver(subject,"WYA"));
    subject->setSubjectStatus(subject,"在线");
    std::cout<<std::endl;
    delete subject;
}

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

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

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
实现观察者模式,首先需要定义一个Observer类,其中包含一个纯虚函数update(),用于接收并处理主题状态的更新。 接下来,创建一个具体的观察者类ConcreteObserver,该类继承自Observer类,并实现update()函数。在该函数中,可以通过调用主题对象的getStatus()函数来获取主题状态的更新,并进行相应的处理。 然后,定义一个主题类Subject,其中包含一个存储观察者对象的容器m_observers。该类提供了添加观察者、删除观察者和通知观察者的功能。在添加观察者时,可以使用m_observers.push_back(observer)将观察者对象添加到容器中;在删除观察者时,可以通过遍历容器找到对应的观察者对象,并使用m_observers.erase(iter)将其从容器中删除;在通知观察者时,通过遍历容器调用每个观察者的update()函数来更新观察者的状态。 这样,就完成了C++实现观察者模式的步骤。通过创建具体的观察者对象并将其添加到主题对象中,当主题状态发生变化时,观察者对象会相应地进行更新。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *2* *3* [设计模式-观察者模式 C++实现](https://blog.csdn.net/u012611878/article/details/72859047)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_1"}}] [.reference_item style="max-width: 100%"] [ .reference_list ]

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

北方以南ccc

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值