接口优化了的观察者模式
来源:互联网 发布:软件流程图模板 编辑:程序博客网 时间:2024/05/21 06:46
接口优化了的观察者模式
之前在写基于MFC实现图表绘制软件的时候, 封装了一个优化接口的观察者模式。不用统一接口也能使用,代码简单清晰。我觉得很有用处,因此在这里分享出来。
1. 实现的效果
优化了接口过后的观察者模式,可以实现让继承自 Subject
的类对普通类进行通知的功能,可以动态的绑定和卸载绑定的响应函数。
- 实现接口
a. 将普通类Ty
的pNonObs
对象的pf
函数关联到通知对象ps
。
template<typename Ty>bool Bind(Subject* ps, Ty* pNonObs, typename Subject::NonObserverRef<Ty>::FuncUpdateRef pf);
b. 将普通类 Ty
的 pNonObs
对象的到 pf
函数与通知对象 ps
解绑。
template<typename Ty>bool UnBind(Subject* ps, Ty* pNonObs, typename Subject::NonObserverRef<Ty>::FuncUpdateRef pf = nullptr);
- 测试效果
a. 样例代码:
#include <iostream>#include "Subject.h"using namespace std;using namespace yl;class NonObserver{public: void Show() { cout << "NonObserver Show..." << endl; } void Show1() { cout << "NonObserver Show1..." << endl; }};class NonObserver1{public: void Show() { cout << "NonObserver1 Show..." << endl; } void Show1() { cout << "NonObserver1 Show1..." << endl; }};//MySubject 继承自Subjectclass MySubject : public Subject{ // Do anything you want...};int main(){ MySubject ms; NonObserver no; NonObserver non; NonObserver1 no1; NonObserver1 non1; //绑定 Bind(&ms, &no, &NonObserver::Show); Bind(&ms, &no, &NonObserver::Show1); Bind(&ms, &no1, &NonObserver1::Show); Bind(&ms, &no1, &NonObserver1::Show1); Bind(&ms, &non1, &NonObserver1::Show); Bind(&ms, &non1, &NonObserver1::Show1); Bind(&ms, &non, &NonObserver::Show); Bind(&ms, &non, &NonObserver::Show1); //发送通知 ms.Notify(); cout << endl; cout << "解绑 ms 对象的所有响应函数..." << endl; UnBind(&ms, &no); //发送通知 ms.Notify(); cout << endl; cout << "解绑 no1 对象的 NonObserver1::Show 响应函数..." << endl; UnBind(&ms, &no1, &NonObserver1::Show); //发送通知 ms.Notify(); cout << endl; cout << "解绑NonObserver1类对象的 Show 响应函数..." << endl; //注意, 如果这里直接用 nullptr 的话, 无法推断类型 UnBind(&ms, (NonObserver1*)nullptr, &NonObserver1::Show1); //发送通知 ms.Notify(); cout << endl; cout << "解绑所有对象的响应函数..." << endl; UnBind(&ms); //发送通知 ms.Notify(); return 0;}
b. 运行结果
NonObserver Show...NonObserver Show1...NonObserver1 Show...NonObserver1 Show1...NonObserver1 Show...NonObserver1 Show1...NonObserver Show...NonObserver Show1...解绑 ms 对象的所有响应函数...NonObserver1 Show...NonObserver1 Show1...NonObserver1 Show...NonObserver1 Show1...NonObserver Show...NonObserver Show1...解绑 no1 对象的 NonObserver1::Show 响应函数...NonObserver1 Show1...NonObserver1 Show...NonObserver1 Show1...NonObserver Show...NonObserver Show1...解绑NonObserver1类对象的 Show 响应函数...NonObserver1 Show...NonObserver Show...NonObserver Show1...解绑所有对象的响应函数...
2. 源代码
Subject.h
文件
/****************************************************************** Program Assignment : 接口优化了的观察者模式* Author: @杨领well(blog.csdn.net/yanglingwell)* Date: 2017/03/15 19:22* Description: 利用模板和重载实现接口优化*****************************************************************/#pragma once#include <list>namespace yl{ class Subject { public: //观察者的基类 class IObserver { public: virtual void Update() = 0; virtual bool operator==(const IObserver&) = 0; virtual void clear() = 0; protected: ~IObserver() {} }; //Subject存响应消息的类的辅助类(adapter) template <typename Ty> class NonObserverRef : public IObserver { public: typedef Ty ObserverType; typedef NonObserverRef<Ty> Type; //响应消息的函数指针类型 typedef void (Ty::*FuncUpdateRef)(); public: NonObserverRef(ObserverType* pNonObserver, FuncUpdateRef updateRef = nullptr) : m_pNonObserver(pNonObserver), m_funcUpdateRef(updateRef) {} public: void Update() override { if (m_funcUpdateRef != nullptr) { (m_pNonObserver->*m_funcUpdateRef)(); } } bool operator==(const IObserver& obs) override { const Type* dObs = dynamic_cast<const Type*>(&obs); if (dObs == nullptr) return false; if (dObs->m_pNonObserver == this->m_pNonObserver) { if (dObs->m_funcUpdateRef == nullptr || m_funcUpdateRef == dObs->m_funcUpdateRef) { return true; } else { return false; } } else if (dObs->m_funcUpdateRef == m_funcUpdateRef && dObs->m_pNonObserver == nullptr) { return true; } else { return false; } } void clear() override { delete this; } private: ObserverType* m_pNonObserver; FuncUpdateRef m_funcUpdateRef; }; public: virtual ~Subject(); public: void Notify(); void Attach(IObserver* pObs) { m_obs.push_back(pObs); } void Detach(IObserver* pObs = nullptr); private: std::list<IObserver*> m_obs; }; //绑定 pNonObs::pf 响应 ps 的通知 template<typename Ty> bool Bind(Subject* ps, Ty* pNonObs, typename Subject::NonObserverRef<Ty>::FuncUpdateRef pf) { if (ps == nullptr || pNonObs == nullptr || pf == nullptr) { return false; } ps->Attach(new typename Subject::NonObserverRef<Ty>(pNonObs, pf)); return true; } //解绑 pNonObs::pf 响应 ps 的通知, 如果 pf==nullptr, 则解绑PNodObs的所有响应函数 template<typename Ty> bool UnBind(Subject* ps, Ty* pNonObs, typename Subject::NonObserverRef<Ty>::FuncUpdateRef pf = nullptr) { if (ps == nullptr && pNonObs == nullptr) { return false; } ps->Detach(new typename Subject::NonObserverRef<Ty>(pNonObs, pf)); return true; } extern bool UnBind(Subject* ps = nullptr);}
b. Subject.cpp
的源码
/****************************************************************** Program Assignment : 接口优化了的观察者模式* Author: @杨领well(blog.csdn.net/yanglingwell)* Date: 2017/03/15 19:22* Description: 利用模板和重载实现接口优化*****************************************************************/#include "Subject.h"using namespace yl;yl::Subject::~Subject(){ Detach();}void yl::Subject::Notify(){ std::list<IObserver*>::iterator iter = m_obs.begin(); while (iter != m_obs.end()) { (*iter++)->Update(); }}void yl::Subject::Detach(IObserver* pObs /*= nullptr*/){ std::list<IObserver*>::iterator iter = m_obs.begin(); while (iter != m_obs.end()) { if (pObs == nullptr || **iter == *pObs) { (*iter)->clear(); iter = m_obs.erase(iter); } else { ++iter; } } if(pObs) pObs->clear();}bool yl::UnBind(Subject* ps /*= nullptr*/){ if (ps == nullptr) return false; ps->Detach(); return true;}
3. 源码下载
github.com
1 0
- 接口优化了的观察者模式
- 一个接口形式的观察者模式
- php系统内置的 观察者模式接口
- java 接口 观察者模式
- 观察者模式(这个用的太多了)
- 被说了很多遍的设计模式---观察者模式
- Observer接口实现观察者模式
- 观察者模式接口传值
- 接口和自定义观察者模式
- 观察者设计模式(Observable 类Observer接口的使用)
- 观察者设计模式(Observable类Observer接口)的实现demo
- 利用观察者模式设计仿真器内核接口
- 观察者模式(设置回调接口)
- 接口回调与观察者模式
- 观察者模式的应用
- 观察者模式的应用
- 增强的观察者模式
- 观察者模式的理解
- Jar包进程Kill前处理完未完成的业务代码
- L2-013. 红色警报
- 蓝桥——未名湖边的烦恼(DP)
- Linux入门
- 阻塞式I/0 和 非阻塞式I/O 同步异步详细介绍
- 接口优化了的观察者模式
- Windows远程访问Mac OS的方法
- AjAX+SSH实现省份下拉菜单
- Vue.js学习系列(二十二)--过滤器
- LeetCode | 496. Next Greater Element I
- 【设计模式】转载23种设计模式
- React Native Android(一) 新建项目,运行,错误解决
- 区间k大数查询
- Service中的绑定服务总结