前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >行为型之观察者模式C++实现

行为型之观察者模式C++实现

作者头像
用户9831583
发布2022-06-16 15:48:37
2060
发布2022-06-16 15:48:37
举报
文章被收录于专栏:码出名企路

现实需求:许多对象并不是独立存在的,其中一个对象的行为发生改变可能会导致一个或者多个其他对象的行为也发生改变。例如,某种商品的物价上涨时会导致部分商家高兴,而消费者伤心;还有,当我们开车到交叉路口时,遇到红灯会停,遇到绿灯会行。

观察者模式:指多个对象间存在一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都得到通知并被自动更新。

优点 :

  1. 降低了目标与观察者之间的耦合关系,两者之间是抽象耦合关系。
  2. 目标与观察者之间建立了一套触发机制。

缺点:

  1. 目标与观察者之间的依赖关系并没有完全解除,而且有可能出现循环引用。
  2. 当观察者对象很多时,通知的发布会花费很多时间,影响程序的效率。

主要角色:

  1. 抽象主题:提供了一个用于保存观察者对象的聚集类和增加、删除观察者对象的方法,以及通知所有观察者的抽象方法。
  2. 具体主题:实现抽象目标中的通知方法,当具体主题的内部状态发生改变时,通知所有注册过的观察者对象。
  3. 抽象观察者:是一个抽象类或接口,包含了一个更新自己的抽象方法,当接到具体主题的更改通知时被调用。
  4. 具体观察者:实现抽象观察者中定义的抽象方法,以便在得到目标的更改通知时更新自身的状态。

具体案例:

小码路上班划水的时候还是有的,身边的伙伴累了大家一起划水嘛,有的伙伴在刷斗音,有的在逛淘宝,但是划水的滋味也不好受啊,时刻要盯着老板是不是要来了。于是,大家想到一个办法,让小码路一个人时刻盯着老板,老板要是来了,及时告诉大家停止划水,继续工作哦哦哦。(当然,内容纯属虚构,小码路和伙伴上班还是很认真的哦)

第一步:抽象主题

代码语言:javascript
复制
#pragma once
#include <iostream>
using namespace std;
#include <list>

class BossListenner;
//通知者的行为抽象为一个接口
class Notifier
{
    public:
        virtual void registerListenner(BossListenner *boss)=0;
        virtual void removeListenner(BossListenner *boss)=0;
        virtual void notify()=0;
};

第二步:具体主题通知者

代码语言:javascript
复制
//小码路作为通知者
class XmlNotifier:public Notifier
{
    public:
        void registerListenner(BossListenner *boss)
        {
            listenners.push_back(boss);
        }
        void removeListenner(BossListenner *boss)
        {
            list<BossListenner*>::iterator it;
            for(it=listenners.begin();it!=listenners.end();it++)
            {
                if(*it==boss)
                {
                    listenners.remove(boss);
                    break;
                }
            }
        }
        void notify();//BossComing实现在其后面,这样会报错,把它拿到最后去实现
       // {
            // list<BossListenner*>::iterator it;
            // for(it=listenners.begin();it!=listenners.end();it++)
            // {
            //     (*it)->BossComing(mValue);
            // }
       // }
        void setValue(int value);
       // {
            // mValue=value;
            // notify();
       // }
    private:
        list<BossListenner*> listenners;
        int mValue;
};

第三步:抽象监听者

代码语言:javascript
复制
//定义一个老板来了的监听者
class BossListenner
{
    public:
        virtual void BossComing(int value)=0;
};

第四步:具体监听者

代码语言:javascript
复制
//具体划水的监听了老板来了这个接口
class SdyPeople:public BossListenner
{
    public:
        void BossComing(int value)
        {
            stopXdy(value);
        }
        void stopXdy(int value)
        {
            cout<<"划水的伙伴停止刷斗音+1,继续工作!"<<value<<endl;
        }
};
class GtbPeople:public BossListenner
{
    public:
        void BossComing(int value)
        {
            stopGtb(value);
        }
        void stopGtb(int value)
        {
            cout<<"划水的伙伴停止逛淘宝+1,继续工作!"<<value<<endl;
        }
};



      void XmlNotifier::notify()
        {
            list<BossListenner*>::iterator it;
            for(it=listenners.begin();it!=listenners.end();it++)
            {
                (*it)->BossComing(mValue);
            }
        }
        void XmlNotifier::setValue(int value)
        {
            mValue=value;
            XmlNotifier::notify();
        }

第五步:主函数

代码语言:javascript
复制
#include "g.h"

int main()
{
    cout<<"老板来了"<<endl;
    XmlNotifier xml;
    SdyPeople xdy;
    GtbPeople gtb;
    xml.registerListenner(&xdy);
    xml.registerListenner(&gtb);
    xml.setValue(1);

    cout<<"老板又来了"<<endl;
    xml.removeListenner(&gtb);
    xml.setValue(2);
}

显示:

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2020-05-10,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 码出名企路 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档