以下关于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. mysql中模糊查询的四种用法介绍

    下面介绍mysql中模糊查询的四种用法: 1,%:表示任意0个或多个字符.可匹配任意类型和长度的字符,有些情况下若是中文,请使用两个百分号(%%)表示. 比如 SELECT * FROM [user] ...

  2. UVa 1346 - Songs

    题目大意:n张唱片,每张都有长度和频率,要求题目中公式值最小.求一个排序,输出该排序下第m张CD的id. 思路:贪心,长度越长放越后面,频率越低放越后面,所以按len/p去排序即可. #include ...

  3. 转载:LBP代码详细注释

    %LBP returns the local binary pattern image or LBP histogram of an image.% J = LBP(I,R,N,MAPPING,MOD ...

  4. 权限分配界面 纯手工 仅用到bootstrap的架构 以及 c标签

    <div class="form-group">        <div class="row">         <label ...

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

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

  6. SQL server 2008 数据库企业版安装教程图解

    SQL Server 2008是一个重大的产品版本,它推出了许多新的特性和关键的改进,使得它成为至今为止的最强大和最全面的SQL Server版本.  在现今数据的世界里,公司要获得成功和不断发展,他 ...

  7. CSS3详解:transform

    CSS3 transform是什么? transform的含义是:改变,使…变形:转换 CSS3 transform都有哪些常用属性? transform的属性包括:rotate() / skew() ...

  8. poj1511 最短路

    题意:与poj3268一样,所有人需要从各点到一点再从一点到各点,求最短路总和. 与poj3268一样,先正向建图跑 dijkstra ,得到该点到其他所有各点的最短路,即这些人回去的最短路,再用反向 ...

  9. 【NOIP2010】【P1317】乌龟棋

    似乎很像搜索的DP(应该也可以用搜索写) 原题: 小明过生日的时候,爸爸送给他一副乌龟棋当作礼物.乌龟棋的棋盘是一行N 个格子,每个格子上一个分数(非负整数).棋盘第1格是唯一的起点,第N 格是终点, ...

  10. java多线程:并发包中ConcurrentHashMap和jdk的HashMap的对比

    一:HashMap--->底层存储的是Entry<K,V>[]数组--->Entry<K,V>的结构是一个单向的链表static class Entry<K, ...