博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
【设计模式】观察者模式(改进后的)
阅读量:5373 次
发布时间:2019-06-15

本文共 4740 字,大约阅读时间需要 15 分钟。

 

前言

之前   中,【通知者】需要知道【观察者】的类名和更新函数名,耦合度稍大,本篇稍稍修改一下,类似于大话设计模式里的C#描述的委托事件的方法。

采用 的方式,把每个【观察者】类的 相同原型的更新函数 指针转换为std::function然后保存起来。

然后在【通知者】的 通知函数 中调用保存起来的每个 【观察者】的更新函数。

本文去除了【观察者】的继承结构,【通知者】只需要知道每个【观察者】的更新函数原型。 

去除了继承结构,因此每个【观察者】的更新函数也就不必是virtual的了。

 

 描述

/************************************************************************//* 设计模式   观察者模式    本文介绍一种解耦的方法,使【通知者】不依赖于【观察者】   即【通知者】不知道【观察者】的太多细节,只需要知道【观察者】   的【更新函数原型】,所以这就要求【观察者】的更新函数的原型   要一致。   以【大话设计模式】里的讲到的Visual Studio的窗口变化为例:    当【启动调试】时,【输出】窗口展开,【反汇编】窗口展开   当【结束调试】时,【输出】窗口隐藏,【反汇编】窗口隐藏   所以这里的【通知者】为【调试器】,【观察者】为【输出】和【反汇编】窗口/************************************************************************/ //调试器的两个行为:启动 和 停止typedef enum _ESubjectState{Start = 0, End = 1}ESubjectState;

 

所需头文件

 

#include "stdafx.h"#include 
#include
#include
#include
#include
using namespace std;

 

 PS:

说到头文件,不得不PS一下下,看头文件里的map,由于在用vector保存std::function时,不能使用std::find函数,也不能在for(iter)中使用if(*iter == std::function XX),因此我试图使用map来保证保存std::functiond唯一性,用map的find来查找待删除的观察者的更新函数。

是试图!!!  经过测试,发现还是不行!

在VC群里HB说因为std::function没有operator ==, 因此不能使用std::find函数, 因此也不能if(*iter == std::function XX),我想map可能是同样的原因。

 

 

 

 

两个观察者

观察者1:输出窗口类

//【观察者】--【输出窗口类】class COutputWnd {public:     COutputWnd();    virtual ~COutputWnd();    void UpdateOutWnd(ESubjectState e);  //更新状态};COutputWnd::COutputWnd(){}COutputWnd::~COutputWnd(){}void COutputWnd::UpdateOutWnd(ESubjectState e){    switch(e)    {    case Start:        cout<<"调试器启动了,展开 输出窗口 \n";        break;    case End:        cout<<"调试器关闭了,收起 输出窗口 \n";    default:        break;    } }

 

 

 

观察者2:反汇编窗口类

//【观察者】--【反汇编窗口类】class CDisassembling {public:    CDisassembling();    virtual ~CDisassembling();    void UpdateDisassembling(ESubjectState e);};CDisassembling::CDisassembling(){}CDisassembling::~CDisassembling(){}void CDisassembling::UpdateDisassembling(ESubjectState e){    switch(e)    {    case  Start:        cout<<"调试器启动了,展开 反汇编窗口 \n";        break;    case End:        cout<<"调试器关闭了,收起 反汇编窗口 \n";        break;    default:        break;    }}

 

 

 

通知者类

 

通知者抽象基类

//【通知者】抽象类class CSubject{public:    typedef std::function
PUpdateFunc; typedef vector
PTRVEC; CSubject(); virtual ~CSubject(); virtual void AddObserer(PUpdateFunc pFunc) = 0; //添加观察者 virtual void RemoveObserver(PUpdateFunc pFunc) = 0; //删除观察者 virtual void Notify(ESubjectState e) = 0; //通知函数protected: PTRVEC m_ptrArr; };CSubject::CSubject(){}CSubject::~CSubject(){}

 

 

 

具体通知者类:调试器类

/**************************************和前一篇将的在使用std::function时的问题类似,这里在函数AddObsererstd中使用std::find函数和RemoveObserver函数中使用std::find函数和opeartor == 时都有问题。 即暂时不能判断vector中没有待插入的函数时才插入, 也不能在删除观察者时查找到后再erase***************************************///【通知者】--【调试器类】class CDebugger : public CSubject{public:    CDebugger();    virtual ~CDebugger();    virtual void AddObserer(PUpdateFunc pFunc);       //添加观察者    virtual void RemoveObserver(PUpdateFunc pFunc);   //删除观察者    virtual void Notify(ESubjectState e);             //通知函数};CDebugger::CDebugger(){}CDebugger::~CDebugger(){}//添加观察者,当待添加的观察者不存在时才添加void CDebugger::AddObserer(PUpdateFunc pFunc){    //if(find(m_ptrArr.begin(), m_ptrArr.end(), pFunc) == m_ptrArr.end())        m_ptrArr.push_back(pFunc); }//删除观察者, 暂时不能删除void CDebugger::RemoveObserver(PUpdateFunc pFunc){     /* PTRVEC::iterator iter = find(m_ptrArr.begin(), m_ptrArr.end(), pFunc);    if(m_ptrArr.end() != iter) m_ptrArr.erase(iter);*/         /*for (PTRVEC::iterator iter = m_ptrArr.begin(); iter != m_ptrArr.end(); ++ iter)    {    } */}void CDebugger::Notify(ESubjectState e){    for (PTRVEC::iterator iter = m_ptrArr.begin(); iter != m_ptrArr.end(); ++ iter)    {         (*iter)(e);     }  }

 

 

 

 

客户端代码

int _tmain(int argc, _TCHAR* argv[]){       //通知者    CSubject* pSubject = new CDebugger();    //三个观察者, 一个是输出窗口, 另外两个是反汇编窗口    COutputWnd objOutPut;    CDisassembling objDisassembling1;    CDisassembling objDisassembling2;        cout<<"-----------添加三个观察者------------"<
AddObserer(func1); CSubject::PUpdateFunc func2 = std::bind(&CDisassembling::UpdateDisassembling, &objDisassembling1, std::placeholders::_1); pSubject->AddObserer(func2); CSubject::PUpdateFunc func3 = std::bind(&CDisassembling::UpdateDisassembling, &objDisassembling2, std::placeholders::_1); pSubject->AddObserer(func3); pSubject->Notify(Start); cout<
Notify(End); cout<
<<"----------把观察者3删除-------------"<
RemoveObserver(func3); pSubject->Notify(Start); cout<
Notify(End); cout<
<

 

 

 

运行结果

 

 

  

  

转载于:https://www.cnblogs.com/cuish/p/3801271.html

你可能感兴趣的文章
从零开始学CSRF
查看>>
【测绘图槽】06 永不放弃励志短片
查看>>
IOS 开发中判断字符串是否为空字符的方法
查看>>
Oracle EBS AR 贷项通知单核销取值
查看>>
权限工作流平台系列-权限工作流版
查看>>
RMA部分接收不成功处理方法
查看>>
CSharp关键字----base
查看>>
eclipse加入git工具
查看>>
mongoose 数据库操作 - 分页
查看>>
Android提高第二篇之SurfaceView的基本使用
查看>>
05_android入门_GET方式实现登陆(在控件上显示服务端返回的内容)
查看>>
spring-01
查看>>
C# 多线程操作实例
查看>>
Android Monkey: “No activities found to run, monkey aborted”错误原因
查看>>
前端组件库1
查看>>
@runWith注解作用
查看>>
微软职位内部推荐-Software Engineer II
查看>>
20145219 《Java程序设计》第08周学习总结
查看>>
linux文件管理 -> 系统压缩打包
查看>>
Android系统文件夹结构
查看>>