每周一荐:设计模式
书籍:《设计模式——改善既有代码的设计》
【简介】
这本书结合设计实作例从面向对象的设计中精选出23个设计模式,总结了面向对象设计中最有价值的经验,并且用简洁可复用的形式表达出来。书中分类描述了一组设计良好、表达清楚的软件设计模式,这些模式在实用环境下特别有用。
【笔记】
23个设计最基础的设计模式,每每读起如醍醐灌顶!不愧为经典之作!
创建型
- Abstract Factory:提供一个创建一系列相关或相互依赖对象的接口,而无须指定它们具体的类
- Builder:将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示
- Factory Method:定义一个用于创建对象的接口,让子类决定实例化那一个类。Factory Method使得一个类的实例化延迟到其子类
- Prototype:用原型实例指定创建对象的种类,并且通过拷贝这些原型创建新的对象
- Singleton:保证一个类仅有一个实例,并提供一个访问它的全局访问点
结构型
- Adapter:将一个类的接口转换成客户希望的另外一个接口。Adapter模式使得原本由于接口不兼容而不能在一起工作的那些类可以一起工作
- Bridge:将抽象部分与它的实现部分分离,使它们都可以独立地变化
- Composite:将对象组合成树形结构以表示”部分-整体”的层次结构。Composite使得用户对单个对象和组合对象的使用具有一致性
- Decorator:动态地给一个对象添加一些额外的职责。就增加功能来说,Decorator模式比生成子类给为灵活
- Facade:为子系统中的一组接口提供一个一致的界面,Facade模式定义了一个高层接口,这个接口使得子系统更加容易使用
- Flyweight:运行共享技术有效地支持大量细粒度的对象
- Proxy:为其它对象提供一种代理以控制对这个对象的访问
行为型
- Chain of Responsibility:使多个对象都有机会处理请求,从而避免请求的发送者和接收者之间的耦合关系。将这些对象连成一条链,并沿着这条链传递该请求,直到有一个对象处理它为止
- Command:将一个请求封装为一个对象,从而使你可用不同的请求对客户进行参数化;对请求排队或记录请求日志,以及支持可撤销的操作
- Interpreter:给定一个语言,定义它的文法的一种表示,并定义一个解释器,这个解释器使用该表示来解释语言中的句子
- Iterator:提供一种方法顺序访问一个聚合对象中的各个元素,而又不暴露该对象的内部表示
- Mediator:用一个中介对象来封装一系列的对象交互。中介者使各对象不需要显式的相互引用,从而使其耦合松散,而且可以独立地改变它们之间的交互
- Memento:在不破坏封装的前提下,捕获一个对象的内部状态,并在对象之外保存这个状态。这样以后就可将该对象恢复到原先保存的状态
- Observer:定义对象间的一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都得到通知并被自动更新
- State:允许一个对象在其内部状态改变时改变它的行为。对象看起来似乎修改了它的类
- Strategy:定义一系列的算法,把他们一个个封装起来,并且使它们可互相替换。本模式使得算法可独立与使用它的客户而变化
- Template Method:定义一个操作中的算法骨架,而将一些步骤延迟到子类中。Template Method使得子类可以不改变一个算法的结构即可重定义该算法的某些特定步骤
- Visitor:表示一个作用于某对象结构中的各元素的操作。它使你可以在不改变各元素的类的前提下定义作用于这些元素的新操作
书籍:《设计模式解析》
【简介】
本书以作者自身学习、使用模式和多年来为软件开发人员(包括面向对象技术老兵和新手)讲授模式的经验为基础撰写而成。首先概述了模式的基础知识,以及面向对象分析和设计在当代软件开发中的重要性,随后使用易懂的示例代码阐明了12个最常用的模式,包括它们的基础概念、优点、权衡取舍、实现技术以及需要避免的缺陷,使读者能够理解模式背后的基本原则和动机,理解为什么它们会这样运作。
【笔记】
对象、封装、面向对象设计不同视角的定义
视角对象封装面向对象设计概念具有责任的一个实体任何形式的隐藏:实现细节、派生类、设计细节、实例化规则共性分析规约接口集合共性分析、变性分析实现数据和方法集合数据隐藏变性分析
优秀代码的目标:
- 高效
- 健壮
- 灵活
- 无冗余
- 可读
- 可测试
面向对象的一些原则和方法
- 内聚性(cohesion):例程中操作之间联系的紧密程度 * 耦合性(coupling):两个例程之间联系的紧密程度
- 软件开发的目标:高内聚、松耦合
- 发现变化并将其封装 1. 寻找变化,并将它封装在一个单独的类中 2. 将这个类包含在另一个类
- 当一个类处理越来越多不同变化时,代码的内聚性就会变得很差。即:它处理的特殊情况越多,可理解性就越差。
- 设计的两步法:1> 抽象类(共性)—— 需要什么接口来出来这个类的所有责任?2> 派生类(可变性)——对于这个给定的特定实现,应该怎样根据给定的规约来实现它?
- 处理新需求的选择: 1> 分析瘫痪;2> 放任自流; 3> 考虑变化的设计
- 考虑变化的设计
- 原则:针对接口编程,而不是针对实现编程
- 原则:优先使用对象组合,而不是类继承
- 原则:考虑设计中什么应该是可变的
- 防止“分支蔓延”
- 一条规则,实现一次
组合起来:用模式思考
- Alexander: 设计应该从问题的一个简单陈述开始,然后通过在这个陈述中加入信息,使它更加详细(也更加复杂)。一种基于模式的方法(《建筑的永恒之道》)
- 从整体的概念性理解开始,以理解需要实现的目标
- 找到整体中出现的模式
- 从为其它模式创造背景的那些模式开始
- 从背景向内:应用这些模式,找到新的模式,并重复
- 最后,通过每次应用一个模式,改进设计,并在所创建的背景中予以实现
- 用模式思考的过程:
- 找出模式
- 分析和应用模式
- 按背景的创建顺序将模式排序
- 选择模式并扩展设计
- 找到其它模式
- 重复
- 添加细节
- 考虑背景时候的一条规则:先考虑系统中需要什么,然后再去关注如何创建它们
- 背景和被使用的关系:当一个模式使用另一个模式时,被使用的模式就处于使用模式的背景中
设计模式的策略:
- 从背景设计
- 在类中封装变化
设计模式的原则:
- 开闭原则——模块、方法和类应该对扩展开放,对修改封闭。换言之,软件应该设计成不加修改缘由代码就能扩展功能。
- 依赖倒置原则——其背后的理念是在设计细节之前先创建总体概念。高层模块不应该依赖底层模块。相反,它们都应该依赖于抽象。
- 理性怀疑原则——小心过分依赖模式。概念层次的模式和模型都是真理的抽象。它们是已往经验和教训的结晶。使用它们来帮助我们思考摆在前面的问题。
共性与可变性分析(CVA):
- 先寻找共性
- 从这些共性创建抽象
- 从共性的变化寻找派生
- 看共性之间的关系如何
分析矩阵:
- 找到某种特定情况中最重要的特性,并用矩阵将它们组织起来。用特性所表示的概念为每个特性标记。
- 继续处理其它情况,安需要扩展这个矩阵。处理每一情况时应该独立于其它情况。
- 用新的概念扩展该分析矩阵
- 用行发现规则
- 用列发现实现
- 从这种分析中确定模式
- 得到高层设计
对象创建和管理规则:对象应该要么构造和/或管理其它对象,要么使用对象,而不应该兼而有之。
常见的设计模式:
- Facade
- Adapter
- Strategy
- Bridge
- Abstract Factory
- Decorator
- Observer
- Template Method
- Singleton 和 Double-Checked Locking
- Object Pool
- Factory Method
2012/03/04 14:00 于上海