C++ Observer设计模式的学习 (Boolan学习笔记第11周)
来源:互联网 发布:手机城市选择器插件js 编辑:程序博客网 时间:2024/05/22 02:31
本周学习了几种设计模式,包括Template, Strategy, Observer, Decorator和Bridge,觉得都有用。本文重点回顾一下Observer设计模式。
Observer设计模式主要应用在当目标对象的状态发生改变的时候,所有的依赖对象(也就是观察者对象)都将得到通知并自动更新。说到”通知”,有嵌入式背景的同学可能马上就会想到用polling和interrupt这两种方法,但我们这里说的设计模式是在应用层,跟底层的OS和hardware无关,其实完全是两个不同领域的东西。
这里要注意的是,目标对象发送通知时,无需指定观察者,通知会自动传播给已经订阅通知的观察者。目标对象并不知道谁是观察者。我们想象这样一个例子,假设有几百万个客户都订阅了一个微信公众号,这个公众号每天都发送一些八卦新闻。客户可以自己选择订阅或退订,公众号的任务就是发送新闻而已,所有的客户在它看来都一样,没有区别。它一发送新闻,那些客户就收到新闻了。这个例子就是一个观察者模式的实际运用。
观察者模式的结构描述如下图:
这里Subject和Observer之间是松耦合。Subject的Notify()里面会调用一个loop,遍历所有的观察者并调用它们的update()函数。在Subject看来所有的观察者都是一样的,它们的update()没有区别。Observer通过订阅/退订,可以决定要不要收到通知。
Observer设计模式在基于时间的UI框架中用的很多。一个具体例子如下:
class IProgress{public: virtual void DoProgress(float value)=0; virtual ~IProgress(){}};class FileSplitter{ string m_filePath; int m_fileNumber; List<IProgress*> m_iprogressList; // 抽象通知机制,支持多个观察者public: FileSplitter(const string& filePath, int fileNumber) : m_filePath(filePath), m_fileNumber(fileNumber){ } void split(){ //1.读取大文件 //2.分批次向小文件中写入 for (int i = 0; i < m_fileNumber; i++){ //... float progressValue = m_fileNumber; progressValue = (i + 1) / progressValue; onProgress(progressValue);//发送通知 } } void addIProgress(IProgress* iprogress){ m_iprogressList.push_back(iprogress); } void removeIProgress(IProgress* iprogress){ m_iprogressList.remove(iprogress); }protected: virtual void onProgress(float value){ List<IProgress*>::iterator itor=m_iprogressList.begin(); while (itor != m_iprogressList.end() ) (*itor)->DoProgress(value); //更新进度条 itor++; } }};class MainForm : public Form, public IProgress{ TextBox* txtFilePath; TextBox* txtFileNumber; ProgressBar* progressBar;public: void Button1_Click(){ string filePath = txtFilePath->getText(); int number = atoi(txtFileNumber->getText().c_str()); ConsoleNotifier cn; FileSplitter splitter(filePath, number); splitter.addIProgress(this); //订阅通知 splitter.addIProgress(&cn); //订阅通知 splitter.split(); splitter.removeIProgress(this); } virtual void DoProgress(float value){ progressBar->setValue(value); }};class ConsoleNotifier : public IProgress {public: virtual void DoProgress(float value){ cout << "."; }};
在这个例子中,FileSplitter是Subject, MainFrame和Console都是客户。FileSplitter切割文件的时候,会调用onProgress()函数。onProgress()就相当于上面图里面的Notify(),里面会遍历m_iprogressList,这个就是客户列表。客户通过splitter.addIProgress()来订阅通知。
另外要注意的是,如果订阅的客户多了,Subject里面的Notify()就会比较慢,变成系统的瓶颈。看来这个Observer模式也是有局限性的。
- C++ Observer设计模式的学习 (Boolan学习笔记第11周)
- C++ 工厂方法设计模式的学习 (Boolan学习笔记第12周)
- C++ Iterator设计模式的思考 (Boolan学习笔记第13周)
- [boolan]设计模式的学习
- [boolan]设计模式学习二
- [boolan]设计模式 观察者学习
- 设计模式学习笔记--观察者(Observer)模式
- 设计模式学习笔记十九(Observer观察者模式)
- 【设计模式】学习笔记2:观察者模式(Observer)
- 设计模式学习笔记-观察者模式(Observer)
- 设计模式C++学习笔记之一(Observer观察者模式)
- boolan——c++学习笔记之设计模式一
- boolan——c++学习笔记之设计模式二
- boolan——c++学习笔记之设计模式三
- Boolan C++设计模式 第一周笔记
- Observer--设计模式学习笔记《二》
- Observer 模式学习笔记
- 设计模式学习--观察者模式(observer)
- 第七单元总结
- orcale常用函数总结
- storm 集群配置
- nginx 配置http2.0
- CentOS7安装 Docker
- C++ Observer设计模式的学习 (Boolan学习笔记第11周)
- ANDROID自定义视图——onMeasure,MeasureSpec源码 流程 思路详解
- TensorFlow学习笔记(2)——保存和加载训练模型参数
- Android中全屏Dialog的实现
- angular post传参 后台接收不到 解决方案
- java io
- AJAX属性介绍
- Android开发-ListView(1)-AndroidStudio
- 如何解决JMeter通过JDBC访问Oracle和MySQL的问题