以下关于GOF的一些例子命名不是很准确,但是大概意思差不多,懒得再去翻书了

 
模拟观察者模式
观察者与职责链模式应该是我们项目中用的最多的了
 
我在之前也写过一篇利用观察者模式对模块进行解耦,当时还是用纯虚函数
 
用纯虚函数来模拟接口是我们之前比较经常使用的方法
这样的缺点是  需要自己去编写接口的纯虚函数,接口的注册和反移除,接口的清理
后来发现了boost的signals库,当需要通知的时候只要负责发送信号就可以了,其他的程序只是负责connect和disconnect,signals库把我从自己编写接口管理代码中解放出来了
与观察者模式相同的是职责链模式,不同的是,职责链模式可以决定消息是否继续往下传递,而signals都会进行传递,所以如果需要职责链,可能还是需要自己去编写手动管理接口的代码
 
 
模拟中介者模式
GOF里面在对中介者模式进行介绍的时候说了设计模式中很重要的一点,就是将行为分散到各个对象中,这个也是我最近在项目代码里面所提倡的,这样的做法就是会降低可复用性
通俗点来讲就是当一个模块的子模块状态发生改变以后,如果通知其他模块或者父模块??
比如要制作图片显示的模块,当图片被放大缩小的时候,有一个文本框需要动态显示当前的比例,我们是怎么通知其他模块的呢??
 
在原来的代码中我们是这样的:
OnZoomIn()
{
parentWindow->NotifyZoomIn();
}
这样,当我们还需要通知另外一个模块A的时候,还需要依赖模块A,所以我们的画图板就依赖了parentWindow,moduleA
这个就是我们原来的编程方式,很奇怪的方式,明明画图板跟模块A和parentWindow没关系却还要去依赖他们
后来学聪明了,就改成这种方式:
     class IPainterNotify
{
virtual void ZoomIn() = ;
virtual ~IPainterNotify() =
{
}
};
OnZoomIn()
{
for(all_notify)
{
notify->ZoomIn();
}
}

这样做的麻烦之处就是我们需要自己去编写接口的管理代码,每一次都要自己定义一大堆的接口,然后自己去写register和unregister,并且经常一个类从其他模块块继承一堆interface,模块耦合很严重

后面看了QT的signal-slot机制,发现wxwidgets加上boost的signals也能做到,不过我认为boost的signals才是正道,像qt的signal需要moc支持,在编译前还需要去修改源文件,而boost的signals则是依赖function-bind机制,function和bind是用C++的模板进行实现的,属于C++自带支持
 当画图板放大或缩小以后,只负责发送信号,其他模块负责提供接口,然后创建的时候互相链接就可以了,这样,各个模块之间都不知道互相之间的存在
 这样就避免了GOF中间提到的面向对象会降低模块的可复用性,并且不需要自己编写接口管理,相对于书中的例子,用signals明显耦合度更低
 
 
利用function模拟command模式(命令模式)
GOF在用command模式的时候举了个例子,就是菜单栏,当我们点击菜单栏以后,要执行一系列的动作,比如openDocument,pastDocument
GOF的做法是定义一个Interface,然后将菜单的响应动作与对应的interface连接起来,这样编码很麻烦,因为我们需要
1.定义interface
2.继承interface
3.实现interface
4.链接interface
 
而且使得事件响应与interface产生了依赖,也使得其他模块对interface产生了依赖
 
我的做法是,定义一个function,然后将function与interface的事件响应bind起来,这样就不用上面那么多步骤了,我们要做的只是链接interface,然后点击菜单后,就直接调用function就可以了,而且两者并不互相依赖,
 
GOF还提到一个历史恢复的问题,比如画图板里面有一个剪切和粘贴功能,将一个图片粘贴后,发现不需要,需要恢复,GOF是再定义一个恢复的接口,这样,每个的command除了有excute的接口,还有一个revert的接口,编码很麻烦,因为在我们的实际项目中,如果需要状态恢复,可不是一个revert接口就够的,还需要一堆的数据,为了绑定这些数据,我们需要继承command的interface,然后传入一堆数据,然后revert的时候根据这些数据进行操作
 
后面我用python的closure后,想起来可以用function模拟这个操作
 
 
利用shared_ptr与function模拟memento和command模式的状态保存和恢复
与command的revert操作类似的还有memento,不过如果按照GOF上面的做法,我们又要定义一个基类,然后从这里面继承一堆子类,用function则不用那么麻烦,因为function可以绑定很多的参数
比如在画图板里面我们需要保存一个点的状态
 

class Point:public boost::enable_shared_from_this<Point>,public IClosure
{
public:
  Point( int x,int y )
  {
    m_x = x;
    m_y = y;
  }
  virtual FUNC_CLOSURE SaveState()
  {
    auto func =
      boost::bind( &Point::SetPoint,this->shared_from_this(),m_x,m_y );
    return func;
  }
  void SetPoint( int x,int y )
  {
    m_x = x;
    m_y = y;
  }
  protected:
  int m_x;
  int m_y;
};
 

这样,当我们需要状态保存的时候,不管是Line,Circle,还是Point,调用SaveState即可,如果按照GOF的comment或者memento,我们可能需要定义一堆的LineState或者CircleState和PointState来支持不同的类型保存和恢复,不过付出的代价就是调试困难,毕竟function里面比较难看到里面的数据

看的不是很懂的模式:visitor模式

我也看得不是很懂这个模式,感觉没什么用,如果把那个accept接口换成function,比直接在基类定义一大堆的A,B,C来的好得多,只需要统一提供一个function就可以了

设计模式的一些杂谈与反思---functionn和signals的更多相关文章

  1. MMO之禅(三)职业能力

    MMO之禅(三)职业能力 --技术九层阶梯 Zephyr 201304 有了精神,我们还需要实际的行动. 到底需要什么能力?自我分析,窃以为为有九层,无所谓高低,因为每一层都需要不断地砥砺,编程,本身 ...

  2. UnitOneSummary

    目录 一.程序结构分析 第一次作业 第二次作业 第三次作业 二.Test & Bugs 三.设计模式 四.总结与反思 一.程序结构分析 第一次作业 思路: 1.输入预处理: 去除空格和\t 替 ...

  3. QT5每日一学(三) QT登陆对话框

    一.使用设计模式创建界面 1.新建Qt Widgets Application,项目名称为login,类名和基类保持MainWindow和QMainWindow不变. 2.完成项目创建后,向项目中添加 ...

  4. iOS设计模式反思之单例模式的进化

    什么是单例模式? 单例模式想一个大独裁者,他规定在他的国度里面,所有数据的访问和请求都得经过他,甚至你要调用相关的函数也得经过它.学术一点就是,单例模式,为某一类 需求和数据提供了统一的程序接口.主要 ...

  5. Android设计模式源码解析之桥接模式

    模式介绍 模式的定义 将抽象部分与实现部分分离,使它们都可以独立的变化. 模式的使用场景 如果一个系统需要在构件的抽象化角色和具体化角色之间添加更多的灵活性,避免在两个层次之间建立静态的联系. 设计要 ...

  6. Java设计模式学习资源汇总

    本文记录了Java设计模式学习书籍.教程资源.此分享会持续更新: 1. 设计模式书籍 在豆瓣上搜索了一把,发现设计模式贯穿了人类生活的方方面面.还是回到Java与程序设计来吧. 打算先归类,再浏览,从 ...

  7. JavaWeb网上商城的反思

    不知道从什么时候起,我爱上了写博客,对之前学得的只是进行反思.写了几天课程设计,代码量量8.9千左右. 然后下面文字是我在博客上复制过来的,说得很详细 MVC(Model View Controlle ...

  8. java_设计模式_观察者模式_Observer Pattern(2016-07-27)

    看了好几篇文章,最终还是觉得<Head First 设计模式>举得例子比较符合观察者模式. 观察者模式概述: 观察者模式有时被称作发布/订阅模式,它定义了一种一对多的依赖关系,让多个观察者 ...

  9. 从SonarQube谈设计模式

    SonarQube SonarQube是用来检测代码质量的,但类似工具的推广常常遇到阻碍. 成型项目或僵尸项目可以理解,项目优化需要投入的人力成本和时间成本太大,而且最主要的是无法保证改动过程中不引入 ...

随机推荐

  1. sdut 2153 Clockwise (2010年山东省第一届ACM大学生程序设计竞赛)

    题目大意: n个点,第i个点和第i+1个点可以构成向量,问最少删除多少个点可以让构成的向量顺时针旋转或者逆时针旋转. 分析: dp很好想,dp[j][i]表示以向量ji(第j个点到第i个点构成的向量) ...

  2. 硬盘缓存的最佳方案,DiskLruCache完全解析

    收藏自:http://blog.csdn.net/guolin_blog/article/details/28863651

  3. Win7下安装双系统Centos,并修复Centos引导加载程序安装在U盘上的问题

    1.使用U盘安装Centos时,磁盘分区划分要注意:系统(包含Win7)只能4个主分区,所以只能在删除一个主分区或者在扩展分区的空闲分区内建立目录. 2.Centos在安装步骤的最后,引导加载程序的选 ...

  4. MACOS,LINUX,IOS上可用的毫秒级精度时间获取

    二话不说,先上代码 void outputCurrentTime(uint32_t seq,const char* type){ struct timeval t_curr; gettimeofday ...

  5. Qt 串口学习2

    未命名 (2) 1 新建串口 //new serial portmy_serialport= new QSerialPort(); 2给串口设定名字 my_serialport->setPort ...

  6. Crawler4j学习笔记

    Crawler4j概述 crawler4j是一款基于Java的轻量级单机开源爬虫框架,最大的一个特点就是简单.另外也支持多线程.支持代理.可以过滤重复URL 基本上从加载jar到工程里面 通过修改示例 ...

  7. NOIP2011 普及組 統計單詞數

    题目描述 一般的文本编辑器都有查找单词的功能,该功能可以快速定位特定单词在文章中的位置,有的还能统计出特定单词在文章中出现的次数. 现在,请你编程实现这一功能,具体要求是:给定一个单词,请你输出它在给 ...

  8. Codeforces Round #144 (Div. 2)

    A. Perfect Permutation 奇偶对调. B. Non-square Equation \(s(x)\)不超过200,根据求根公式计算\(x\). C. Cycles 每次新增点时都和 ...

  9. ..c++中用c语言的输入法

    题目: 竞选时,要求选民在n个候选人中选择,n个人的名字为 A,B,C,D--连续n个大写字母,如果选择n个人名字之外的人员,则为废票.   统计时以输入'#'为结束标记.请按候选人的得票数目从大到小 ...

  10. console下纯字符实现的俄罗斯方块

    忙里偷闲,消遣一下,先上一张寒酸的效果图: 废话不多说,直接上代码,win7 64 code blocks编译通过. 吐槽一下cb的watch功能实在不够友好,不过免费的也不能要求太高. [按键说明] ...