本系列所有文章来自李建忠老师的设计模式笔记,系列如下:
设计模式(一)面向对象设计原则
23种设计模式(二)组件协作之模板方法
23种设计模式(三)组件协作之策略模式
23种设计模式(四)组件协作之观察者模式
23种设计模式(五)单一职责之装饰模式
23种设计模式(六)单一职责之桥模式
23种设计模式(七)对象创建之工厂方法
23种设计模式(八)对象创建之抽象工厂
23种设计模式(九)对象创建之原型模式
23种设计模式(十)对象创建之构建器
23种设计模式(十一)对象性能之单件模式
23种设计模式(十二)对象性能之享元模式
23种设计模式(十三)接口隔离之门面模式
23种设计模式(十四)接口隔离之代理模式
23种设计模式(十五)接口隔离之适配器
23种设计模式(十六)接口隔离之中介者
23种设计模式(十七)状态变化之状态模式
23种设计模式(十八)状态变化之备忘录
23种设计模式(十九)数据结构之组合模式
23种设计模式(二十)数据结构之迭代器
23种设计模式(二十一)数据结构之职责链
23种设计模式(二十二)行为变化之命令模式
23种设计模式(二十三)行为变化之访问器
23种设计模式(二十四)领域规则之解析器

文章目录

  • 设计方法一
  • 设计方法二
  • 模式定义
  • 要点总结

  现代软件专业分工之后的第一个结果是“框架与应用程序的划分”,“组件协作”模式通过晚期绑定,来实现框架与应用程序之间的松耦合,是二者之间协作时常用的模式。

  典型模式可以分为:Template MethodStrategyObserver / Event

  观察者模式:在软件构建过程中,我们需要为某些对象建立一种“通知依赖关系” ---- 一个对象(目标对象)的状态发生改变,所有的依赖对象(观察者对象)都将得到通知。如果这样的依赖关系过于紧密,将使软件不能很好地抵御变化。

假设我们做一个文件分割器,将大的文件分割成多个文件:

设计方法一

  • MainForm1.cpp
class MainForm : public Form
{TextBox* txtFilePath; // 文件路径TextBox* txtFileNumber; // 希望分割的文件个数ProgressBar* progressBar;public:void Button1_Click(){// 接收用户传进来的两个信息string filePath = txtFilePath->getText();int number = atoi(txtFileNumber->getText().c_str());FileSplitter splitter(filePath, number, progressBar);splitter.split(); // 调用split方法}
};

  首先我们需要一个界面,所以我们继承Form类,之后接收用户的输入信息,之后划分文件。

  • FileSplitter1.cpp
class FileSplitter
{string m_filePath;int m_fileNumber;ProgressBar* m_progressBar;public:FileSplitter(const string& filePath, int fileNumber, ProgressBar* progressBar) :m_filePath(filePath), m_fileNumber(fileNumber),m_progressBar(progressBar){}void split(){//1.读取大文件//2.分批次向小文件中写入for (int i = 0; i < m_fileNumber; i++){//...float progressValue = m_fileNumber;progressValue = (i + 1) / progressValue;m_progressBar->setValue(progressValue);}}
};

  现在有一个需求,希望提供文件处理的进度展示,很自然的想法就是在split中计数,然后在MainForm中展示。也就是上述代码m_progressBar所处理的事情。

  但是上述方法违背了依赖倒置设计原则:高层模块不能依赖底层模块,二者都应该依赖于抽象,抽象不能依赖于实现细节,实现细节应该依赖于抽象。

  ProgressBar* m_progressBar;这行代码可能并不能适用于别的显示进度方式。

设计方法二

  • MainForm2.cpp
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 << ".";}
};
  • FileSplitter2.cpp
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++;}}
};

  第二种方式看似是将progressBar->setValue(value);放到了MainForm2.cpp文件中,其实是有很大的不同。

模式定义

  定义对象间的一种一对多(变化)的依赖关系,以便当一个对象(Subject)的状态发生改变时,所有依赖于它的对象都得到通知并自动更新。

要点总结

  使用面向对象的抽象,Observer模式使得我们可以独立地改变目标与观察者,从而使二者之间的依赖关系达致松耦合。

比如在MainForm2.cpp文件中添加多少个观察者都无所谓,但是在FileSplitter2.cpp文件中的addIProgressremoveIProgressonProgress函数都不会改变。

  目标发送通知时,无需指定观察者,通知(可以携带通知信息作
为参数)会自动传播。

比如onProgress函数中只需要传入一个值即可,通知会自动传播。

  观察者自己决定是否需要订阅通知,目标对象对此一无所知。

  Observer模式是基于事件的UI框架中非常常用的设计模式,也是MVC模式的一个重要组成部分。

23种设计模式(四)组件协作之观察者模式相关推荐

  1. 李建忠讲23种设计模式笔记-上

    前两天在B站看了李建忠老师讲23种设计模式的系列视频,收获颇丰.设计模式是前人的智慧和经验的总结,需要我们反复地学习.在实践中体会其蕴含的设计原则和设计思想.李老师按照封装变化将23种设计模式分成组件 ...

  2. 【23种设计模式】观察者模式(Observer Pattern)

    个人主页:金鳞踏雨 个人简介:大家好,我是金鳞,一个初出茅庐的Java小白 目前状况:22届普通本科毕业生,几经波折了,现在任职于一家国内大型知名日化公司,从事Java开发工作 我的博客:这里是CSD ...

  3. 【每天一个java设计模式(完)】 - 四万字实现23种设计模式(附示例源码)

    什么是设计模式:[每天一个java设计模式(零)] - 设计模式基本概念及七大设计原则 创建型模式 工厂模式:[每天一个java设计模式(一)] - 工厂模式 抽象工厂模式: [每天一个java设计模 ...

  4. 我们的23种设计模式(四)

    23种设计模式总结与分析override4 19 Memento(备忘录)模式 20 Template Method(模板方法)模式 21 Status(状态)模式 22 Interpreter(解释 ...

  5. 23种设计模式(十四)模板方法模式(阁瑞钛伦特软件-九耶实训)

    常说的设计模式是23种设计模式,分为3大类: 创建型模式5种:工厂方法.抽象工厂.单例.建造者.原型 结构型模式7种:适配器.代理.桥接.装饰者.外观.享元.组合 行为型模式11种:模板方法.解释器. ...

  6. 简单易懂23种设计模式——观察者模式【含C++代码实例】

    23种设计模式C++实现--观察者模式 在做面向对象的软件开发时我们往往想达到更高的代码可复用性和更合理的软件颗粒度. 根据<设计模式--可复用面向对象软件的基础>所说:"你必须 ...

  7. java 23种设计模式详解

    1. 软件设计模式意义 文章链接:http://c.biancheng.net/design_pattern/     设计模式的本质是对面向对象设计原则运用,是对类的封装.继承和多态以及类的关联关系 ...

  8. 从Android代码中来记忆23种设计模式

    原文链接:http://www.jianshu.com/p/1a9f571ad7c0 相信大家都曾经下定决心把23种设计模式牢记于心,每次看完之后过一段时间又忘记了~,又得回去看,脑子里唯一依稀记得的 ...

  9. java与23种设计模式

    1 23种设计模式分类 经典的<设计模式>一书归纳出23种设计模式,本文按<易学设计模式>一书归纳分类如下: 1.创建型模式 前面讲过,社会化的分工越来越细,自然在软件设计方面 ...

  10. 23种设计模式介绍以及在Java中的实现

    本文章出自:blog.csdn.net/anxpp/artic- 若要查看原文请点击 文章中的示例源码在github上:github.com/anxpp/JavaD- 由于CSDN上的下拉翻页比较麻烦 ...

最新文章

  1. Valve className=org.apache.catalina.valves.AccessLogValve directory=logs prefix=localhost_acce
  2. 访问网络计算机的盘符,win7系统下如何禁止访问指定盘符保护电脑安全
  3. 【活动】厦门.NET俱乐部 省上云开发者专场
  4. java8自定义收集器_使用自定义收集器进行Java 8分组?
  5. [算法][算法复杂度]常用算法复杂度速查表
  6. 和gdi绘图效率比较_绘图计算器测评来袭!哪一款才是你AP考试的最佳拍档?
  7. Matplotlib作业一
  8. Servlet技术详解
  9. ASP.NET MVC:UrlHelper.cs
  10. 网上的PS把图片变清晰的原理
  11. apply,call,bind重新定义this的区别
  12. CentOS NFS
  13. 单细胞三大R包之Seurat
  14. 请每一个孝顺的子女耐心的看下去!
  15. cu116安装gpu版pytorch
  16. python控制excel选择区域_python针对excel的操作技巧
  17. 移动端和前端开发的共性
  18. 汇编语言(王爽)实验十
  19. python人脸识别系统库_GitHub - mybug/face_collection: python的face_recognition人脸识别库的使用...
  20. 重点领域知识工程课程群虚拟教研室建设启动会暨第一次教学研讨会在线召开...

热门文章

  1. NHibernate查询语言(HQL)
  2. python 流式编程_Java8 Stream流式编程,极大解放你的生产力!
  3. HCIE Security 双机热备 备考笔记(幕布)
  4. Tomcat详解(十一)——Tomcat管理
  5. shell 第一次练习
  6. 深入浅出理解死锁(以吃鸡游戏为例)
  7. KVM图形管理界面打不开(virt-manager 报错)
  8. PTA(BasicLevel)-1009 说反话
  9. Android_adb shell am/pm使用
  10. Android之notificaction使用