初读GoF经典

GoF的经典之作,介绍了21个设计模式,并给出了这些模式的相互关系,如何在实际的设计中选择和运用,演化这些模式。

花了三个下午,很快的通读了一下,把自己记住的东西和理解记下来,以后可以不断补充。

设计模式的核心思想是要封装变化,让设计可以在变化中保持相对的稳定,这也刚好符合了,敏捷方法中拥抱变化的思想,所以模式是敏捷方法成功的必要技术。

同时,设计模式的描述的几个关键的部分:

  1. 意图(可以解决的问题的一般/抽象描述)
  2. 动机(产生出来的CASE,即所解决的问题的具体描述)
  3. 结构和交互
  4. 适用情况
  5. 效果(优缺点)

让印证了GoF在6.5章节关于重构中介绍的,这里介绍的模式都是在平常项目的OO设计的不断扩展和重构中总结出来的。所以,运用模式确实可以 避免到很多不必要得重构工作。但是,个人认为,对设计的反思和重构是有益的,有机会可以看看关于重构的文献。

简单写一下我所理解的21个设计模式:

创建性模式:抽象了系统如何创建对象实例。

  1. 抽象工厂,透明地创建一系列相关的对象
  2. 工厂方法,透明地创建一个与实现工厂方法的对象所依赖的对象,通常是XXXModifier等等
  3. Builder,创建复杂对象的时候,可以按照一个对象的创建脚本/蓝图来创建,而如何创建复杂对象中元素的方法可以透明地变化。
  4. 单体,保证只有一个对象实例创建,是全局变量的很好的代替品,为了让单体是线程安全的,可以采用双检查枷锁。
  5. 原型,这是动态load新的类到系统中,并创建这些动态load进入系统类的实例的唯一办法。也是,欧感觉很聪明的一种创建模式。

结构模式:描述了使用对象来构建更大的系统的方法

  1. Adapter,把一个已经有的接口改造成另一个借口,这用可以复用这个已有的对象实现。有类方法和对象方法。
  2. Bridge,把一个子系统的分成接口和实现两个类层次,这样接口和实现可以独立地改变。
  3. Composite,如何把系统表示成递归的结构,而且可以用统一的方法来处理原子对象和组合对象,“树“是最好的抽象结构。
  4. Decorator,不用继承这样的静态方法来给对象增加功能,而是创建一个实现了新功能的新对象并把所有旧对象的旧功能直接代理给旧的对象,这就支持了对象功能的动态增加和撤销。
  5. Facade,给一个子系统提供一个单一的,容易理解和使用的接口。
  6. Flyweight,一个好的设计,可以避免系统产生大量的很细小的对象。对象的属性被分成,编译时的/静态的/内在的 vs. 运行时的/动态的/外部的,只有编译时的的属性被放在这些对象中,其他的运行时属性被作为对象方法的Context参数在运行时传入。
  7. Proxy,如果要隐藏子系统的外部特殊细节/或添加特殊附加功能,通常要给子系统增加proxy,以简化客户对子系统的访问。譬如:远程代理(远程调用),虚代理(create-when-necessary的逻辑),保护代理(安全检查和保护逻辑),智能reference(引用计数,动态加载,撤销的逻辑)。这是很常用和重要的一个模式,可以说基本上每一个子系统在重构时都会产生proxy,不过是不同的代理类型。

OO设计的思想就是,系统由相互依赖的对象组成。所谓依赖,就是对象相互通讯/调用,对象间依赖关系,设计的是否有效,直接决定了系统的运行是否有效;依赖关系是否松散,直接表现为设计是否可以有效地复用以应对面对变化。所以:

  1. 如何有效地为各个对象分配职责(OO设计中最重要的“荒岛技术”)。
  2. 如何有效地定义对象通讯的策略,以达到效率和松散耦合的平衡。

对象之间通讯的方式,本质上来讲只有两种:请求 vs. 消息。从耦合的程度来讲,一般认为,请求比消息的耦合大,消息只是数据耦合,但是,毕竟是都有耦合。所以,为了要面对变化的需求,我们需要改变请求/消息的发送者和接受者。如果我们设计的通讯策略,可以让我们在改变一方的时候,另一方不需要改变,那么我们也就有效地复用了不需要改变的一方。

行为模式:描述了这两个OO设计的核心方面,所以行为模式是最多,也是最丰富的。在UML中,协作通常由交互图或者顺序图来描述。

  1. 职责链,让多个对象都有机会来处理请求,这样就可以对请求发送对象透明地、动态地改变响应请求的对象。ACE STREAM FRAMEWORK就是这个模式的实现框架。
  2. 命令,把请求,和接受请求的对象索引,一起封装在一个命令对象中,这样就避免了命令的请求者(Invoker)和命令的接受者之间的耦合,也可以让命令支持排序、批量处理、撤销等事务操作。
  3. 迭代器,有效地为集合对象提供顺序访问集合元素的设计。可以很好的把集合的内部结构,集合元素的排序和遍历算法封装在了Iterator中。很多,STL地容器都有自己的迭代器。
  4. 中介(Meidator),把多个对象之间如何协作的逻辑封装在了中介里,这样协作的多个对象,相互就没有了直接的耦合,各自变化不会波及到其他的对象中去。
  5. 备忘录(Memento),可以在不破坏一个对象的封装的情况下,把对象的内部状态纪录下来。其实,它最大的好处是,可以让具有备忘录的对象,可以很容易地实现回滚。
  6. 观察着(Obserever ),如何来实现对象间一对多,或者多对多的依赖。通常,复杂的依赖关系,还会引入一个改变管理器(mediator ),来管理发生改变消息的传播。这是最重要,最常用的行为模式,因为OO就是多个对象相互依赖(通讯而达到协作)。
  7. 状态机(STATE ),在具有庞大的判断逻辑的算法中,把算法设计成为形式化的状态机是必然的选择,state模式给OO提供了一个实现状态机的合理抽象,即抽象出状态这个对象。经管,把状态机抽象成为状态转换表示最经典和常用的,不过如果对象的行为特性是由状态来控制行为,那么仅仅通过状态转换表来定义状态转换,是不够的。这时,就要借助state模式了。
  8. 策略(Strategy),策略把对象行为中的算法/逻辑抽象为策略,并设计为可以改变的。这是一个很好的替代继承而改变对象行为的方法。通常,会把对象的类,设计为可策略化的类模板。
  9. 模板方法,定义一个行为的步骤骨架,而把步骤地实现都放到子类中去。
  10. 访问者(VISITOR ) ,如果对象的内部结构很复杂,同时这个对象的某个操作的逻辑需要分散到对象的各个组成元素中去,那就会让操作逻辑内嵌在各个元素中,很难维护和应对变化(牵一发而动全身)。所以,vistor把本来分散在各个元素中的对元素的access逻辑,都提取出来,集中到一个访问者对象中,成为访问者对象的各个访问方法。这是双/多分派(double/multi-dispatch )在不支持多分派的语言(如C++)中的一个实现。
  11. 解释器(Interpreter),没有看出这个模式有什么特别的地方。

最后,提一下,个人认为最常用和重要的两个设计模式:Proxy , Observer。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值