关于c++观察者模式的理解

观察者模式,有时又称为发布-订阅模式,是软件设计模式的一种,在这个模式中,当被观察者发生改变时,会主动通知所有关注它的观察者,它的一个大致实现原理是:被观察者类中,有一个容器,当有观察者关注它时,被观察者会将这个观察者添加到这个容器中,被观察者有事件发生时,会遍历这个容器,通知所有关注它的观察者。

具体实现方法:被观察者发生事件的时候,如何通知观察者呢?通常做法是直接调用观察者的某个方法,但是这样做的坏处是,增加了类之间的耦合性,不利于以后程序的扩展。正确的做法是:不直接调用类,把观察者和被观察者都写一个基类,在基类里边调用,要使用的时候继承基类,实现具体的方法。

下面是我画的一个大概的框图,红色虚线就是数据的传递过程,也就是通知的触发过程
这里写图片描述
明白了一个大概的实现原理,下边直接上代码

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

using namespace std;

//被观察者,先声明,因为观察者的类里边用到
class CObservable;

//观察者 这里定义一个纯虚基类,用来连接观察者和被观察者
class CObserver 
{
public:
    CObserver(){};
    virtual ~CObserver(){};
    virtual void Updata(CObservable * pObs,void * pArg=NULL)=0;//纯虚函数
};

//定义被观察者基类
class CObservable 
{
public:
    CObservable() :m_bChanged(false) {};
    virtual ~CObservable() {};

    void AddObs(CObserver *pObs);//添加观察者
    void DelObs(CObserver *pObs);//删除观察者
    void DelAllObs();
    bool HasChanged();//查看是否有事件变化
    void Notify(void *pArg=NULL);//事件触发


protected:
    void SetChanged();//设置目标变化
    void ClearChanged();//清除目标变化

private:
    bool m_bChanged;
    set<CObserver *> m_setObs;//保存观察者列表,当有事件发生的时候,遍历通知里边的观察者
};
//添加观察者
void CObservable::AddObs(CObserver *pObs)
{
    if (!pObs) return;
    m_setObs.insert(pObs);
}
//删除观察者
void CObservable::DelObs(CObserver * pObs)
{
    if (!pObs) return;
    m_setObs.erase(pObs);
}
//删除所有观察者
void CObservable::DelAllObs()
{
    m_setObs.clear();
}
//通知观察者
void CObservable::Notify(void * pArg)
{
    if (!HasChanged()) return;//如果没有变化,不用通知,直接返回
    cout << "Notify Observer....";
    set<CObserver*>::iterator itr = m_setObs.begin();//定义观察者的迭代器,遍历通知观察者集合里边的所有元素
    for (; itr != m_setObs.end(); itr++)
    {
        (*itr)->Updata(this,pArg);//调用观察者的方法
    }

}
bool CObservable::HasChanged()
{
    return m_bChanged;
}
void CObservable::SetChanged()
{
    m_bChanged = true;
}
void CObservable::ClearChanged()
{
    m_bChanged = false;
}





//具体应用类
//定义一个被观察者
class CBlogs :public CObservable//继承被观察者基类
{
public :
    void Publish(const string &strContend) {//定义自己的方法
        cout << "blogs publish" << strContend << endl;
        SetChanged();//有事件发生,给基类设置标志位
        Notify(const_cast<char*>(strContend.c_str()));//调用通知观察者方法
    }
};
//定义一个被观察者
class CPortal :public CObservable
{
public:
    void Publish(const string &strContend) {
        cout << "portal publish" << strContend << endl;
        SetChanged();
        Notify(const_cast<char*>(strContend.c_str()));
    }
};


//定义观察者
class CRssreder :public CObserver 
{
public:
    CRssreder(const string &strName) :m_strName(strName) {}//设置观察者名称
    virtual void Updata(CObservable * pObs, void * pArg=NULL) {//必须实现观察者基类的纯虚函数
        char *pContent = static_cast<char*>(pArg);//转换参数
        if (dynamic_cast<CBlogs*>(pObs)) {//判断是哪个被观察者触发的
            cout <<m_strName<< "updata from CBlogs contend:" << pContent << endl;
        }
        if (dynamic_cast<CPortal*>(pObs)) {
            cout << m_strName << "updata from CPortal contend:" << pContent << endl;
        }
    }
private:
    string m_strName;
};



//使用
int main() 
{
    //定义被观察者
    CBlogs * pBloger = new CBlogs();
    CPortal * pPortal = new CPortal();

    //定义观察者
    CRssreder * pCRssReader = new CRssreder("rss reader");

    pBloger->AddObs(pCRssReader);//注册观察者
    pPortal->AddObs(pCRssReader);

    pBloger->Publish("博客分享");//被观察者有事件发生
    cout << endl;

    pPortal->Publish("门户分享");
    cout << endl;

    system("pause");
    return 0;
}
使用场景:通常被用来实现事件处理系统,因为被观察者里边定义的存放观察者的容器的类型是观察者基类,所以继承于这个观察者的类都可以调用,这样就大大增加了程序的灵活性

参考:https://baike.baidu.com/item/%E8%A7%82%E5%AF%9F%E8%80%85%E6%A8%A1%E5%BC%8F/5881786?fr=aladdin

  • 0
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
以下是一个简单的 C++ 观察者模式实现的代码示例: ``` #include <iostream> #include <vector> using namespace std; class Observer { public: virtual void update() = 0; }; class Subject { private: vector<Observer*> observers; public: void attach(Observer* observer) { observers.push_back(observer); } void detach(Observer* observer) { observers.erase(std::remove(observers.begin(), observers.end(), observer), observers.end()); } void notify() { for (Observer* observer : observers) { observer->update(); } } }; class ConcreteObserver1 : public Observer { public: void update() { cout << "ConcreteObserver1 received the update." << endl; } }; class ConcreteObserver2 : public Observer { public: void update() { cout << "ConcreteObserver2 received the update." << endl; } }; class ConcreteSubject : public Subject { public: void doSomething() { cout << "ConcreteSubject is doing something." << endl; notify(); } }; int main() { ConcreteSubject subject; ConcreteObserver1 observer1; ConcreteObserver2 observer2; subject.attach(&observer1); subject.attach(&observer2); subject.doSomething(); subject.detach(&observer2); subject.doSomething(); return 0; } ``` 在这个实现中,我们定义了一个 Observer 接口和一个 Subject 类。具体的观察者 ConcreteObserver1 和 ConcreteObserver2 实现了 Observer 接口,而具体的被观察者 ConcreteSubject 继承了 Subject 类。 ConcreteSubject 类中有一个 doSomething() 方法,它会触发 notify() 方法,通知所有注册过的观察者。被观察者可以通过 attach() 方法注册观察者,detach() 方法注销观察者。 在 main() 函数中,我们创建了 ConcreteSubject 和两个 ConcreteObserver 的实例,注册了这两个观察者,然后调用 doSomething() 方法触发通知。我们还演示了如何注销一个观察者,然后再次触发通知。 这个简单的实现可以帮助你理解观察者模式的基本原理和实现方式。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值