设计模式(002) 模式语录
《Design Patterns:Elements of Reusable Object-Oriented Software》尽管是英文描述的,了解和喜欢设计模式的同仁看到这个书目,熟悉得犹如看到下面这张图:
当你发现这不是一张完整的图的时候,不要以为被我忽悠了,即便你是被我善意地小小忽悠了一下,但你忽悠不了你自己(GOF的设计模式),很快其他部分自然而然的在你脑海里呈现出来。如果说你还没有打算现在或者将来去学习和使用设计模式来改善自己的编码和设计,请你不要觉得我在故弄玄虚,因为设计模式是一个老生常谈的东西了,为什么老生常谈东西,还要拿出来扯一扯呢?这样来回答这个问题,为什么老生常谈的东西,我们还不熟悉呢?还不去学习呢?如果你是一个正在学习设计模式,期望通过掌握这些来改善自己的编码设计以及提升自己的职业生涯,那么我们是很适合交个朋友(当然得你愿意),一起交流学习。如果你是设计模式高手了,在你茶余饭后,不小心扫过此文后,给我一点您宝贵的建议,期待您的指点以及我自己的提升。
我很喜欢GOF在书中一开始对设计模式的描述。设计模式的四要素:模式名称(What)、问题(Where)、解决方案(How)、效果(Why),括号中是我曾经从老师那学习到的3W1H方针,也就是“模式A通过B方案解决了C问题,达到了D效果”。或许我这么总结起来有些牵强附会了,果真吗?来看看GOF对设计模式的四要素的描述:
- 模式名称:一个助记名,它用一两个词汇来描述模式的问题、解决方案和效果。设计模式允许我们在较高的抽象层次上进行设计。基于一个模式词汇表,我们自己以及同事之间就可以讨论模式并在编写文档是使用它们。模式名有助于我们思考,以便我们与其他人交流设计思想及设计结果。
- 问题:描述应该在何时使用模式。它解释了设计问题和问题的前因后果,它可能描述了特定的设计问题,如怎样用对象的表示算法等等。也可能描述了导致不灵活设计的类或对象结构。有时候,问题部分会包括使用模式必须满足的一系列先决条件。
- 解决方案:描述了设计的组成成分,他们之间的互相关系以及各自的职责和协作方式。因为模式想一个模板,可应用于多种不同场合,所以解决方案并不描述一个特定而具体的设计或实现,而是提供设计问题的抽象描述和怎样用一个具有一般意义的元素组合来解决问题。
- 效果:描述了模式应用的效果及使用模式应权衡的问题。尽管我们描述设计决策时,并不总提到模式效果,但它们对于评价设计选择和了理解使用模式的代价及好处具有重要意义。软件效果大多数关注对时间和空间的衡量,它们也表述了语言和实现问题。因为复用是面向对象设计的要素之一,所以模式效果包括它对系统的灵活性、扩充性或可一致性的影响,显示地列出这些效果对理解和评价这些模式很有帮助。
这些专业的描述不免让我们读起来有些抽象,但是,GOF还说了:设计模式是被用来在特定场景下解决一般设计问题的类和相互通信的对象的描述。(通过改善这些设计让程序更加内聚,让系统更加灵活,易扩展,易维护等)。所以,让我们暂时放下那么专业的描述吧,用3W1H武装自己,去解读设计模式。的确有时候,尽管我们全力以赴了,还是不尽人意,比如说GOF说的那句话,我们并没有和3W1H对应起来,爱思考的你会说,怎么去解决呢?为什么这么做呢?好像没有描述,以至于我自己用一个括号来补充了为什么这么做。至于怎么做?这就是我们要学习设计模式的核心了,弄清楚What、Where、Why之后,How to do?,用大师一句话:“骚年,路就在脚下...”
本文并没有打算对23设计模式进行详细的描述,如果你迫不及待想学习设计模式了,我给推荐一些书:《大话设计模式》、《Head First 设计模式》、《设计模式解析》、《重构与模式》、当然还有本文提到的这本书,但是别着急,接下来会有一些有趣的事情,让你5分钟通读23中设计模式,用3W1H武装好自己,心中有巨人,勇往直前吧,勇士们!
这里我不再对设计模式的分类进行详细的描述了,我们都知道,设计模式按照目的可以分为一下三种:
- 创建型:单例、工厂方法、抽象工厂、建造者、原型
- 结构型:适配、代理、装饰、组合、外观、享元、桥接。
- 行为型:策略、模板方法、状态、命令、迭代器、观察者、访问者、备忘录、责任链、解释器、中介者。
我曾这样思考过,模板方法是不是作为结构型更好呢?既然是在父类中定义好了一个算法的骨架,让子类在不改变算法的结构的前提下去定义该算法的某些特定步骤。定义好的算法骨架和结构,字里行间都是一种结构的体现,然而遗憾的是,GOF和业界都没有将它归纳到结构类型中,我仔细琢磨:让子类去定义该算法的某些特定步骤,这确实是行为的体现,子类重新定义了行为,那么问题就来了,这个模式如果侧重点是提供一个固定的算法骨架,是不是结构更重要了,如果更侧重让子类更灵活和方便重新定义行为,这个就偏向行为了。公说公有理,婆说婆有理,在思考一点点,固定的算法骨架不就是为了给子类重新定义行为提供方便的吗,减少子类不必要的工作。从这种目的性出发,也吻合了根据目的去区分的宗旨,模板方法中的固定算法骨架存在的目的是为行为提供服务的,那么说他是行为型,是有道理的。
PS:模式类型其实真的没有想象的那么重要,搞清楚它是来做什么的,能解决什么问题更重要-----3W1H
另外根据范围准则,可以分为两种:
- 类模式:适配器(类适配器)、工厂方法、模板方法、解释器
- 对象模式:适配器(对象适配器)、...、...
不要认为这里是笔误,适配器的确有类模式和对象模式,暂不讨论这个问题。
来到本文的主旨,一起来通读23种设计模式,我叫它为设计模式一句话语录:
- 单例(Singleton):保证一个类有且仅有一个实例,并提供一个访问它的全局访问点。(我更倾向于这样的描述:保证一个类最多有一个实例...)
- 工厂方法(Factory Method):定义一个用于创建对象的接口,让子类决定将哪一个类实例化。将一个类的实例化延迟到子类。(这里的接口不是特指interface)
- 抽象工厂(Abstract Factory):提供一个创建一系列相关或相互依赖对象的接口,而无需指定它具体的类。(貌似有些抽象)
- 建造者(Builder):将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示。(有点类似于敏捷开发中的最佳实践:分离构造和使用)
- 原型(Prototype):用原型实例指定创建对象的种类,并且通过拷贝这个原型来创建新的对象。(好比一个模具,我们用它去批量生产产品)
- 适配器(Adapter):将一个类的接口转换成客户希望的另一个接口,使得原本由于接口不兼容而不能一起工作的那些类可以一起工作。(充电器就是一个适配器)
- 代理(Proxy):为其他对象提供一个代理以控制对这个对象的访问。(经纪人好像更像一个代理)
- 装饰(Decorator):动态的给一个对象添加一些额外的职责,就扩展功能而言,装饰模式比生成子类的方式更为灵活。(组合优于继承)
- 组合(Composite):将对象组合成树形结构以表示“部分-整体”的层次结构,使得客户对单个对象和复合对象的使用具有一致性。(给用户提供透明化的使用方式)
- 外观(Facade):为子系统的一组接口提供一个一致的界面,Facade模式定义了一个高层接口,这个接口使得这一子系统更加易用。(统观全局往往更好把握方向)
- 享元(Flyweight):运用共享技术有效地支持大量细粒度的对象。(共享使得不会因为对象过多造成资源的紧张和浪费)
- 桥接(Bridge):将抽象部分与它的实现部分分离,使得它们都可以独立变化。(这也是组合优于继承的情景)
- 策略(Strategy):定义一系列的算法,把它们一个个封装起来,并且使它们可以互相替换。策略模式使得算法的变化独立于使用它们的客户。(封装变化,提高内聚性)
- 模板方法(Template Method):定义一个操作中的算法骨架,而将一些步骤延迟到子类中,使得子类可以不改变算法的结构即可重新定义该算法的某些特定步骤。
- 状态(State):允许一个对象在其内部状态改变时改变它的行为,对象看起来似乎修改了它所属的类。(不同的状态干不同的事,这很符合人的特点)
- 命令(Command):将一个请求封装为一个对象,从而使得你可用不同的请求对客户进行参数化,对请求排队或记录请求日志,以及支持可取消操作。(工作中最常见的一种,比如说编辑文档)
- 迭代器(Iterator):提供一种方法顺序访问一个聚合对象中各个元素,而又不需要暴露该对象内部表示。(让封装进行到底)
- 观察者(Obsever):定义对象之间的一种一对多的依赖关系,以便当一个对象的状态发生改变时,所有依赖它的对象都得到通知并自动更新。(手机天气预报APP)
- 访问者(Visitor):表示一个作用于某对象结构中的各个元素的操作,它使得你可以在不改变各元素类的前提下定义作用于这些元素的新操作。
- 备忘录(Memento):在不破坏封装性的前提下,捕获一个对象的内部状态,并在该对象之外保存这个状态,这让以后可以将该对象恢复到保存的状态。(游戏进度保存)
- 责任链(Chain of Responsibility):为解除请求的发送者和接收者之间的耦合,而使多个对象都有机会处理这个请求,将这些对象连成一条链,并沿着这条链传递该请求,直到有一个对象处理它。(公司的工作流有点类似的行为)
- 解释器(Interpreter):给定一个语言,定义它的文法的一种表示,并定义一个解释器,该解释器使用该表示来解释语言中的句子。(歌谱1234567的翻译)
- 中介者(Mediator):用一个中介对象来封装一系列的对象交互,中介者使得对象不需要显示地互相引用,从而使其耦合松散,而且可以独立改变它们之间的交互。(最少知识原则的运用)
23中设计模式都全了,5分钟读完还是有些吃力的,因为读的过程中还要思考,没关系,再快速扫一扫下面这张图,不要盯着看太久:
要命了吧,此刻建议休息片刻,广告之后,可以不用回来,否则头脑紊乱概不负责,已经到尾声了,这张图对于初学者来说是比较费劲的,但还是建议多看多思考,在脑海留个影像,好比我上次在路上行走听到了这样一段对话(6岁左右儿子:“这两个车撞了,为什么个车好着,另一个车破了。” 爸爸:“因为这个车的钢结构是什么什么做的...”),你会笑这个爸爸吗,给那么小的儿子讲钢结构,孩子啥都不懂,但是这个爸爸这么做是有道理的,这时候给儿子讲了,他记住了,那天他学习到了,那就是他解惑而获得真理的时候了。所以不要认为这些对这些看似跟自己无关的东西不理不睬,做一个有心人,时间会告诉你,你已经跑在前面了。
以上内容完全不用去记它,你可以将这篇文章保存下来,作为设计模式类目,或者将这个内容复制保存到本地,或者或者或者.......