设计模式的一些杂谈与反思---functionn和signals

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

模拟观察者模式

模拟中介者模式

模拟command模式

模拟memento和command

模拟观察者模式

观察者与职责链模式应该是我们项目中用的最多的了

 

我在之前也写过一篇利用观察者模式对模块进行解耦,当时还是用纯虚函数

http://www.cnblogs.com/linyilong3/p/4232529.html

用纯虚函数来模拟接口是我们之前比较经常使用的方法

这样的缺点是  需要自己去编写接口的纯虚函数,接口的注册和反移除,接口的清理

后来发现了boost的signals库,当需要通知的时候只要负责发送信号就可以了,其他的程序只是负责connect和disconnect,signals库把我从自己编写接口管理代码中解放出来了

与观察者模式相同的是职责链模式,不同的是,职责链模式可以决定消息是否继续往下传递,而signals都会进行传递,所以如果需要职责链,可能还是需要自己去编写手动管理接口的代码

 

 

模拟中介者模式

GOF里面在对中介者模式进行介绍的时候说了设计模式中很重要的一点,就是将行为分散到各个对象中,这个也是我最近在项目代码里面所提倡的,这样的做法就是会降低可复用性

通俗点来讲就是当一个模块的子模块状态发生改变以后,如果通知其他模块或者父模块??

比如要制作图片显示的模块,当图片被放大缩小的时候,有一个文本框需要动态显示当前的比例,我们是怎么通知其他模块的呢??

 

在原来的代码中我们是这样的:

OnZoomIn()
{
    parentWindow->NotifyZoomIn();
}

这样,当我们还需要通知另外一个模块A的时候,还需要依赖模块A,所以我们的画图板就依赖了parentWindow,moduleA

这个就是我们原来的编程方式,很奇怪的方式,明明画图板跟模块A和parentWindow没关系却还要去依赖他们

后来学聪明了,就改成这种方式:

 1     class IPainterNotify
 2     {
 3         virtual void ZoomIn() = 0;
 4         virtual ~IPainterNotify() = 0
 5         {
 6         }
 7     };
 8     OnZoomIn()
 9     {
10         for(all_notify)
11         {
12             notify->ZoomIn();
13         }
14     }

这样做的麻烦之处就是我们需要自己去编写接口的管理代码,每一次都要自己定义一大堆的接口,然后自己去写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就可以了

时间: 2024-10-05 18:36:38

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

设计模式之反思(一)

这几天,师哥给我们讲了一下设计模式.让我们从学习方法及对各个模式的理解重新洗礼了一遍.在此,我整理了一下自己的笔记及自己的一些感受. 一.结构型 结构型模式处理的是类与类或者说对象与对象的关系. 1.外观模式-Facade (1) 此模式定义了一个高层接口,从而使子类更容易使用,并提供了一个统一的界面. (2)优点: 将用户和子系统分开,减少其耦合度,有利于系统维护,同时扩展性也比较好 (3)原则: 符合迪米特法则,违背了开闭原则 2.桥接模式-Bridge 如图,我们可以看出桥接模式的主体架构

重构中对设计模式的反思

什么是设计模式? 每一类编程语言都具有其自身的特性,就像是面向对象的语言,其特性就是封装,继承,多态,抽象. 同一时候,使用每一类编程语言开发软件时也都有一些设计准则,这些准则保证了软件的质量,即具有良好的设计. 而设计模式则是广大软件开发者总结出的开发经验技巧,它们利用编程语言的特点,实现这些准则.因此,能够想象,当我们对设计模式熟悉到一定程度后,在设计系统时.我们眼里就会变得没有设计模式,仅仅有设计准则,真正达到手中无剑.心中有剑的境地. 在学习设计模式时.到底要学什么?      曾经.在

软件设计模式与设计风格的反思

以前编码只是关注能写出来,并让程序运行就完事,这是非常错误的想法. 重新理解软件设计,要考虑如何设计函数接口更加容易理解,而不是写成什么样的函数能表达现在的业务理解. 函数或者类的设计除了要考虑业务,还需要从品味上入手,这个品味就是易读,美观,想想python之禅.

2015.7个人反思小结以及后续规划

2015.7个人反思小结以及后续规划 标签(空格分隔): 反思小结 缘由: 总觉得有必要为自己写一篇小结,有些东西会跟随着时光慢慢被淡忘,写小结感觉和拍照一样,都是用来 记录自己曾经的点点滴滴,以后某一天回头看到这篇小结,可能会会心一笑,哈哈,曾经自己也这样傻逼过: 反思下自己的过去,看下自己的现在,规划以后的方向~,给自己一点鸡汤,打打鸡血,一点点让自己成为一个 优秀的人~ 过去: 在今年的7月4号,小猪的大学生涯终于到了尽头,可惜并没有拿到正常毕业拿到的两个证:学位证跟毕业证:只拿到一个象征

设计模式(创建型)之原型模式(Prototype Pattern)

PS一句:最终还是选择CSDN来整理发表这几年的知识点,该文章平行迁移到CSDN.因为CSDN也支持MarkDown语法了,牛逼啊! 概述 原型模式是一种创建型设计模式,它通过复制一个已经存在的实例来返回新的实例,而不是新建实例.被复制的实例就是我们所称的原型,这个原型是可定制的.原型模式多用于创建复杂的或者耗时的实例, 因为这种情况下,复制一个已经存在的实例可以使程序运行更高效,或者创建值相等,只是命名不一样的同类数据. 原型模式要求对象实现一个可以"克隆"自身的接口,这样就可以通过

饕餮盛宴之设计模式

老师集合八期.九期的师哥师姐,倾心准备了一场饕餮盛宴.为之三天的设计模式的讲解,不仅仅让我们巩固了知识,开拓了眼界,还让我们对好的学习方法有了更清晰真切的了解.这次模式的讲解,感觉收获颇丰. 一.总体思想 1.看待问题要简单.抽象 学习一个东西,要学会极端化的来对待它,先从简单的开始.我们往往会选取一个中间值来讲解,结果把别人搞晕了,自己也晕了. 2.学习要脚踏实地,搞懂的越晚,付出的代价越大 学习的初期,尽可能要还原学习的原貌,搞懂它,这样在学习的后期才能走的更轻松.如果现在能搞懂却不愿意弄懂

JAVA学习第十课(单例设计模式)

杂谈: 如果一个类里的方法都是静态的,那么就没有必要创建对象,为了不让其他程序创建对象,就可以把当前类的构造函数私有化. class MAN { private MAN() { } } 文档注释:命令:javadoc 只能解析/** 开始至 */结束的内容:/* */则不行 路径设置问题: 当要运行,两个以上路径中的class文件时,路径都要设置,命令:classpath=.;c:\myhelp或者:classpath=.;%myhelp% 清除路径: set classpath= 设计模式:对

转载--C++的反思

转载自http://blog.csdn.net/yapian8/article/details/46983319 最近两年 C++又有很多人出来追捧,并且追捧者充满了各种优越感,似乎不写 C++你就一辈子是低端程序员了,面对这种现象,要不要出来适时的黑一下 C++呢?呵呵呵. 咱们要有点娱乐精神,关于 C++的笑话数都数不清: 笑话:C++是一门不吉祥的语言,据说波音公司之前用ADA为飞机硬件编程,一直用的好好的,后来招聘了一伙大学生,学生们说我靠还在用这么落后的语言,然后换成C++重构后飞机就

设计模式之适配器模式--- Pattern Adapter

模式的定义 适配器模式(Adapter Pattern)定义如下: Convert the interface of a class into another interface clients expect.Adapter lets classes work together that couldn't otherwise because of incompatible interface. 将一个类的接口变换成客户端所期待的另一种接口,从而使原本因接口不匹配而无法在一起工作的两个类能够在一起