50
设计模式浅析 刘易成

设计模式浅析

Embed Size (px)

Citation preview

设计模式浅析刘易成

⽣生活中的模式

⽣生活中的模式

• 模式是Pattern的汉译。

• 所谓Pattern就是⼀一种规则,或是⼀一种模型,或是⼀一种习惯。

• Pattern这个东⻄西到处都是,并不只有技术圏⼦子⾥里才有。

超级英雄

谈恋爱• 产⽣生好感 • 搭讪,相识 • 吃饭,看电影 • 牵⼿手,拥抱...

• ⻅见家⻓长 • 结婚 • ⽣生孩⼦子

桥梁设计

桥梁设计

桥梁设计

桥梁设计

桥梁设计 - 组合

新闻联播

• 头10分钟领导很忙

• 中间10分钟⼈人民很幸福

• 后10分钟国外很乱

定义

定义(wikipedia)• 它是对软件设计中普遍存在(反复出现)的各种问题,所提出的解决⽅方案。

• 设计模式并不直接⽤用来完成代码的编写,⽽而是描述在各种不同情况下,要怎么解决问题的⼀一种⽅方案。

• 设计模式能使不稳定依赖于相对稳定、具体依赖于相对抽象,避免会引起⿇麻烦的紧耦合,以增强软件设计⾯面对并适应变化的能⼒力。

定义(书)

• 它描述了在⾯面向对象软件设计过程中针对特定问题的简洁⽽而优雅的解决⽅方案。

• 设计模式使⼈人们可以更加简单⽅方便地复⽤用成功的设计和体系结构。

• 每⼀一个模式描述了⼀一个在我们周围不断重复发⽣生的问题,以及该问题的解决⽅方案的核⼼心。这样,你就能⼀一次⼜又⼀一次的使⽤用该⽅方案⽽而不必做重复劳动。

定义(其他)• 设计模式(Design pattern)是⼀一套被反复使⽤用、多数⼈人知晓的、经过分类编⺫⽬目的、代码设计经验的总结。

• 使⽤用设计模式是为了可重⽤用代码、让代码更容易被他⼈人理解、保证代码可靠性

• 程式設計是思維具體化的⼀一種⽅方式,是思考如何解決問題的過程,設計模式是在解決問題的過程中,⼀一些良好思路的經驗集成。

来历

四⼈人帮

《设计模式》

• Erich Gamma, Richard Helm, Ralph Johnson, John Vlissides

!

• Design Patterns - Elements of Reusable Object-Oriented Software

设计模式有哪些

分类• 创建型模式(5)

• 创建型模式与对象的创建有关 • 结构型模式(7)

• 结构型模式处理类或对象的组合 • ⾏行为型模式(11)

• ⾏行为型模式对类或对象怎样交互和怎样分配职责进⾏行描述

表述格式• 模式名:每⼀一个模式都有⾃自⼰己的名字,模式的名字使得我们可以讨论我们的设计。

• 问题:在⾯面向对象的系统设计过程中反复出现的特定场合,它导致我们采⽤用某个模式。

• 解决⽅方案:上述问题的解决⽅方案,其内容给出了设计的各个组成部分,它们之间的关系、职责划分和协作⽅方式。

• 别名:⼀一个模式可以有超过⼀一个以上的名称。这些名称应该要在这⼀一节注明。

• 动机:该模式应该利⽤用在哪种情况下是本节提供的⽅方案(包括问题与来⻰龙去脉)的责任。

• 适⽤用性:模式适⽤用于哪些情况、模式的背景等等。

• 结构:这部分常⽤用类图与交互图阐述此模式。

• 参与者:这部分提供⼀一份本模式⽤用到的类与对象清单,与它们在设计下扮演的⾓角⾊色。

• 合作:描述在此模式下,类与对象间的交互。

• 影响:采⽤用该模式对软件系统其他部分的影响,⽐比如对系统的扩充性、可移植性的影响。影响也包括负⾯面的影响。这部分应描述使⽤用本模式后的结果、副作⽤用、与权衡(trade-off)

• 实现:这部分应描述实现该模式、该模式的部分⽅方案、实现该模式的可能技术、或者建议实现模式的⽅方法。

• ⽰示例:简略描绘出如何以编程语⾔言来使⽤用模式。

• 已知应⽤用:业界已知的实作⽰示例。

• 相关模式:这部分包括其他相关模式,以及与其他类似模式的不同。

创建型模式

• Abstract Factory 抽象⼯工⼚厂

• Builder ⽣生成器

• Factory Method ⼯工⼚厂⽅方法

• Prototype 原型

• Singleton 单件

结构型(Structural)模式

• Adapter 适配器

• Bridge 桥接

• Composite 组成

• Decorator 装饰

• Facade 外观

• Flyweight 享元

• Proxy 代理

⾏行为(Behavioral)模式• Chain of Responsibility 职责链

• Command 命令

• Interpreter 解释器

• Iterator 迭代器

• Mediator 中介者

• Memento 备忘录

• Observer 观察者

• State 状态

• Strategy 策略

• Template Method 模板⽅方法

• Visitor 访问者

设计模式之间的关系

介绍⼏几种常⻅见的设计模式

Abstract Factory 抽象⼯工⼚厂

定义

• 提供⼀一个创建⼀一系列相关或相互依赖对象的接⼝口,⽽而⽆无需指定它们具体的类。

形象描述• 追MM少不了请吃饭了,⻨麦当劳的鸡翅和肯德基的鸡翅都是MM爱吃的东⻄西,虽然⼝口味有所不同,但不管你带MM去⻨麦当劳或肯德基,只管向服务员说“来四个鸡翅”就⾏行了。⻨麦当劳和肯德基就是⽣生产鸡翅的Factory

• ⼯工⼚厂模式:客户类和⼯工⼚厂类分开。消费者任何时候需要某种产品,只需向⼯工⼚厂请求即可。消费者⽆无须修改就可以接纳新产品。缺点是当产品修改时,⼯工⼚厂类也要做相应的修改。如:如何创建及如

类图

举例假设我们有两种产品接⼝口 Button 和 Border ,每⼀一种产品都⽀支持多种系列,⽐比如 Mac 系列和

Windows 系列。这样每个系列的产品分别是 MacButton, WinButton, MacBorder, WinBorder 。为了可以在运⾏行时刻创建⼀一个系列的产品族,我们

可以为每个系列的产品族创建⼀一个⼯工⼚厂 MacFactory 和 WinFactory 。每个⼯工⼚厂都有两个⽅方法 CreateButton 和 CreateBorder 并返回对应的产

品,可以将这两个⽅方法抽象成⼀一个接⼝口 AbstractFactory 。这样在运⾏行时刻我们可以选择创

建需要的产品系列。

举例

适⽤用性

• 在以下情况可以考虑使⽤用抽象⼯工⼚厂模式 • ⼀一个系统要独⽴立于它的产品的创建、组合和表⽰示时。

• ⼀一个系统要由多个产品系列中的⼀一个来配置时。

• 需要强调⼀一系列相关的产品对象的设计以便进⾏行联合使⽤用时。

• 提供⼀一个产品类库,⽽而只想显⽰示它们的接⼝口⽽而不是实现时。

Adapter 适配器

定义

• 将⼀一个类的接⼝口转换成客户希望的另外⼀一个接⼝口。Adapter 模式使得原本由于接⼝口不兼容⽽而不能⼀一起⼯工作的那些类可以⼀一起⼯工作。

形象描述

• 在朋友聚会上碰到了⼀一个美⼥女Sarah,从⾹香港来的,可我不会说粤语,她不会说普通话,只好求助于我的朋友kent了,他作为我和Sarah之间的Adapter,让我和Sarah可以相互交谈了(也不知道他会不会耍我)

• 适配器(变压器)模式:把⼀一个类的接⼝口变换成客户端所期待的另⼀一种接⼝口,从⽽而使原本因接⼝口原因不匹配⽽而⽆无法⼀一起⼯工作的两个类能够⼀一起⼯工作。适配类可以根据参数返还⼀一个合适的实例给客户端。

类图 - Object Adapter

类图 - Class Adapter

举例

• 封装后端接⼝口

适⽤用性• 以下情况使⽤用 Adapter 模式

• 你想使⽤用⼀一个已经存在的类,⽽而它的接⼝口不符合你的需求

• 你想创建⼀一个可以复⽤用的类,该类可以与其他不相关的类或不可预⻅见的类(即那些接⼝口可能不⼀一定兼容的类)协同⼯工作。

• (仅适⽤用于对象 Adapter)你想使⽤用⼀一些已经存在的⼦子类,但是不可能对每⼀一个都进⾏行⼦子类化以匹配他们的接⼝口。对象适配器可以适配它的⽗父类接⼝口。

Observer 观察者

定义

• 定义对象间的⼀一种⼀一对多的依赖关系,当⼀一个对象的状态发⽣生改变时,所有依赖于它的对象都得到通知并被⾃自动更新。

形象描述

• 想知道咱们公司最新MM情报吗?加⼊入公司的MM情报邮件组就⾏行了,tom负责搜集情报,他发现的新情报不⽤用⼀一个⼀一个通知我们,直接发布给邮件组,我们作为订阅者(观察者)就可以及时收到情报啦

• 观察者模式:观察者模式定义了⼀一种⼀一对多的依赖关系,让多个观察者对象同时监听某⼀一个主题对象。这个主题对象在状态上发⽣生变化时,会通知所有观察者对象,使他们能够⾃自动更新⾃自⼰己。

类图

举例 - javascript 事件模型• 观察者模式(Observer Pattern),也被称为“发布/订阅模型(publisher/subscriber model)”。

• 在这种模式中,有两类对象,分别是“观察者-Observer”和“⺫⽬目标对象-Subject”。

• ⺫⽬目标对象中保存着⼀一份观察者的列表,当⺫⽬目标对象的状态发⽣生改变的时候就主动向观察者发出通知(调⽤用观察者提供的⽅方法),从⽽而建⽴立⼀一种发布/订阅的关系。

• 这⼀一种发布/订阅的关系常⽤用于实现事件、消息的处理系统。

举例 - JAVA

举例 - DOM

举例 - JavaScript

适⽤用性• 在以下任⼀一情况下可以使⽤用观察者模式:

• 当⼀一个抽象模型有两个⽅方⾯面,其中⼀一个⽅方⾯面依赖于另⼀一个⽅方⾯面。将这两者封装在独⽴立的对象中以使它们可以各⾃自独⽴立地改变和复⽤用

• 当对⼀一个对象的改变需要同时改变其他对象,⽽而不知道具体有多少对象有待改变。

• 当⼀一个对象必须通知其他对象,⽽而它⼜又不能假定其他对象是谁。换⾔言之,你不希望这些对象是紧密耦合的。