文章目录
- 一、 面向对象基础
- 2. 面向对象分析(Object-Oriented Analysis,OOA)
- 3. 面向对象设计(Object-Oriented Design,OOD)
- 4. 面向对象程序设计(Object-Oriented Programming,OOP)
- 5. 面向对象测试
- 二、 UML(Unified Modeling Language,统一建模语言)
- 2. 关系
- 3. UML 中的图
-
- (1)类图(Class Diagram)
- (2)对象图(Object Diagram)
- (3)用例图(Use Case Diagram)
- (4)交互图
- ② 通信图(Communication Diagram)
- ③ 交互概览图(Interaction Overview Diagram)
- ④ 计时图(Timing Diagram)
- (5)状态图(State Diagram)
- (6)活动图(Activity Diagram)
- (7)构件图(Component Diagram)
- (8)组合结构图(Composite Structure Diagram)
- (9)部署图(Deployment Diagram)
- (10)包图(Package Diagram)
- 三、 设计模式
- 2. 创建型设计模式
- 3. 结构型设计模式
- 4. 行为设计模式
一、 面向对象基础
面向对象(Object-Oriented,OO)方法:一种非常实用的系统化软件开发方法,它以客观世界中的对象为中心,其分析和设计思想符合人们的思维方式,分析和设计的结果与客观世界的实际比较接近,容易被人们所接受。
1. 面向对象的基本概念
面向对象 = 对象(Object) + 分类(Classification) + 继承(Inheritance) + 通过消息的通信(Communication with Messages)
(1)对象
是基本的运行时的实体
,它既包括数据(属性),也包括作用于数据的操作(行为)。一个对象把属性和行为封装【一种信息隐蔽技术,目的:使对象的使用者和生产者分离,使对象的定义和实现分开】为一个整体。
(2)消息
对象之间进行通信的一种构造。
(3)类
是在对象之上的抽象,对象是类的具体化,是类的实例(Instance)。一个类定义了一组大体上相似的对象。一个类所包含的方法和数据描述一组对象的共同行为和属性。
类可以分为三种:实体类【其对象表示现实世界中真实的实体】、接口类(边界类)【其对象为用户提供一种与系统合作交互的方式,分为人和系统两大类】和控制类【其对象用来控制活动流,充当协调者】。
(4)继承
是父类和子类之间共享数据和方法的机制,是类之间的一种关系。在定义和实现一个类的时候,可以在一个已经存在的类的基础上进行,把这个已经存在的类所定义的内容作为自己的内容,并加入若干新的内容。
一个父类可以有多个子类,这些子类都是父类的特例,父类描述了这些子类的公共属性和方法。一个子类可以继承它的父类(或祖先类)中的属性和方法,这些属性和操作在子类中不必定义,子类中还可以定义自己的属性和方法。
B 只从一个父类 A 得到继承,叫作“单重继承”。如果一个子类有两个或更多个父类,则称为“多重继承”。
(5)多态(Polymorphism)
不同的对象收到同一消息产生完全不同的结果。
多态有不同的形式,参数多态:应用比较广泛的多态,被称为最纯的多态。
(6)动态绑定(Dynamic Binding)
静态绑定:在编译时进行的绑定。
动态绑定:在运行时进行的绑定,是和类的继承以及多态相联系的。
绑定:一个把过程调用和响应调用所需要执行的代码加以结合的过程。
2. 面向对象分析(Object-Oriented Analysis,OOA)
将数据和功能结合在一起作为一个综合对象来考虑,可以将系统的行为和信息间的关系表示为迭代构造特征。面向对象分析的基础是软件系统结构,这依赖于人类看待现实世界的方法。
目的:为了获得对应用问题的理解【目的:确定系统的功能、性能要求】。
(1)认定对象
在应用领域中,按自然存在的实体确立对象。
在定义域中,首先将自然存在的“名词”作为一个对象。
困难在于寻找(选择)系统关心的实质性对象,实质性对象是系统稳定性的基础
。
(2)组织对象
抽象类时可从对象间的操作或一个对象是另一个对象的一部分来考虑,由对象抽象类,通过相关类的继承构造类层次,所以说系统的行为和信息间的分析过程是一种迭代表征过程。
(3)对象间的相互作用
可以完整地描述每个对象的环境,由一个对象解释另一个对象,以及一个对象如何生成另一个对象,最后得到对象的界面描述。
(4)基于对象的操作
其操作有:从对象直接标识的简单操作;也有更复杂的操作。一般而言,避免对象太复杂比较好,当连接的对象太复杂时,可将其标识为新对象。
确定了对象的操作后,再定义对象的内部,包括:内部数据信息、信息存储方法、继承关系以及可能生成的实例数等属性。
3. 面向对象设计(Object-Oriented Design,OOD)
将 OOA 所创建的分析模型转化为设计模型,目标:定义系统构造蓝图。
通常的情况是,由概念模型生成的分析模型被装入到相应
OOA 与 OOD
之间不存在鸿沟,采用一致的概念和一致的表示法,OOD同样应遵循抽象、信息隐蔽、功能独立、模块化等设计准则。
(1)面向对象设计的活动
OOD 在复用 OOA 模型的基础上,包含与 OOA 对应的
5 5
个活动:识别类及对象、定义属性、定义服务、识别关系、识别包。OOD应该尽可能隔离实现条件对系统的影响,对不可隔离的因素按实现条件调整OOA模型。
要使系统的结构好且效率高,做好相互间的平衡是困难的。分析模型已经提供了概念结构,它将试图长期保存。另外,设计期必须充分考虑系统的稳定性、可靠性和响应时间等,所有这些都会影响系统的结构。
对象标识期间的目标是分析对象,设计过程也是发现对象的过程,称之为再处理,并补充几个新的组成部分,即与实现有关的因素。
(2)面向对象设计的原则
- 单一责任原则(Single Responsibility Principle,SRP)
一个类,应该仅有一个引起它变化的原因,让一个类只做一种类型责任。 - 开放-封闭原则(Open & Close Principle,OCP)
软件实体(类、模块、函数等)应该是可以扩展的,即开放的;但是不可修改的,即封闭的。 - 里氏替换原则(Liskov Substitution Principle,LSP)
子类型必须能够替换掉他们的基类型。 - 依赖倒置原则(Dependence Inversion Principle, DIP)
抽象不应该依赖于细节,细节应该依赖于抽象。 - 接口分离原则(Interface Segregation Principle,ISP)
不应该强迫客户依赖于它们不用的方法。接口属于客户,不属于它所在的类层次结构。 - 重用发布等价原则(Release Reuse Equivalency Principle,REP)
重用的粒度就是发布的粒度。 - 共同封闭原则(Common Closure Principle,CCP)
包中的所有类对于同一类性质的变化应该是共同封闭的。 - 共同重用原则(Common Reuse Principle,CRP)
一个包中的所有类应该是共同重用的。 - 无环依赖原则(Acyclic Dependencies Principle,ADP)
在包的依赖关系图中不允许存在环,即包之间的结构必须是一个直接的五环图形。 - 稳定依赖原则(Stable Dependencies Principle,SDP)
朝着稳定的方向进行依赖。 - 稳定抽象原则(Stable Abstractions Principle,SAP)
包的抽象程度应该和其稳定程度一致。 - 迪米特原则(最少知识法则)
一个对象应当对其他对象有尽可能少的了解。
4. 面向对象程序设计(Object-Oriented Programming,OOP)
实质:选用一种面向对象程序设计语言(Object-Oriented Programming
Language,OOPL),采用对象、类及其相关概念所进行的程序设计。关键在于加入了类和继承性,从而进一步提高了抽象程度。
程序设计范型(Programming
Paradigm):人们在程序设计时所采用的基本方式模型,决定了程序设计时采用的思维方式、使用的工具,同时又有一定的应用范畴。
(1)类
具有实例化功能,包括实例生成(由类的Constructor完成)和实例消除(由类的Destructor完成)。类的实例化功能决定了类及其实例具有以下特征:
- 同一个类的不同实例具有相同的数据结构,承受的是同一方法集合所定义的操作,因而具有规律相同的行为。
- 同一个类的不同实例可以持有不同的值,因而可以具有不同的状态。
- 实例的初始状态(初值)可以在实例化时确定。
(2)承和类层次结构
在一个面向对象系统中,子类与父类之间的继承关系构成了这个系统的类层次结构,可以用树(对应于单继承)或格(对应于多继承)这样的图来描述。
OOPL
中的继承机制体现了一条重要的面向对象程序设计原则:开发人员在构造程序时不必从零开始,而只需对差别进行程序设计。支持继承也是
OOPL 与传统程序设计语言在语言机制方面最根本的区别。
(3)对象、消息传递和方法
对象是类的实例。它们之间存在本质区别:对象之间通过消息传递方式进行通信。
消息传递源:一种与通信有关的概念,OOP
使得对象具有交互能力的主要模型就是消息传递模型。对象被看成用传递消息的方式互相联系的通信实体,它们既可以接收,也可以拒绝外界发来的消息。
(4)对象自身引用(self-Reference)
是
OOPL中的一种特有结构。对象自身引用的值和类型分别扮演了两种意义的角色:对象自身引用的值使得方法体中引用的成员名与特定的对象相关;对象自身引用的类型则决定了方法体被实际共享的范围。
在程序运行过程中,消息传递机制和对象自身引用将方法与特定的对象动态地联系在一起,使得不同的对象在执行同样的方法体时,可以因对象的状态不同而产生不同的行为,从而使得方法对具体的对象具有个性。
(5)重置
重置或覆盖(Overriding)是在子类中重新定义父类中已经定义的方法。基本思想:通过一种动态绑定机制的支持,使得子类在继承父类接口定义的前提下用适合自己要求的实现去置换父类中的相应实现。
(6)类属类
类属是程序设计语言中普遍注重的一种参数多态机制,在OOPL中也不例外。
一个重要作用:对类库的建设提供了强有力的支持,重置和类属都是一种多态机制。
类属类可以看成是类的模板。一个类属类是关于一组类的一个特性抽象,它强调的是这些
类的成员特征中与具体类型无关的那些部分,而与具体类型相关的那些部分则用变元来表示。
(7)无实例的类
如果存在继承关系,在类层次结构的较高层次上有始终没有实例的类。
5. 面向对象测试
在所有开发系统中都是根据规范说明来验证系统设计的正确性,程序验证应尽可能早地开始。程序调试步骤是从最底层开始,从单元测试【系统构件的分体测试】、综合测试【将测试好的系统构件接起来看它们之间相互作用的正确性】到系统测试【包括软件系统所在相关环境的测试】。
单元测试比传统系统的单元大,综合测试尽可能在早期阶段处理,因为通信是系统开发的实质。所有对象有预定义的界面,这也有利于综合测试。当综合测试继续到较高层次时,那么越来越多的对象就会被逐步连接起来。面向对象的综合测试是由底向上
的测试。一般来说,对面向对象软件的测试分为
4 4 个层次进行:
- 算法层
测试类中定义的每个方法,基本上相当于传统软件测试中的单元测试。 - 类层
测试封装在同一个类中的所有方法与属性之间的相互作用。在面向对象软件中类是基本模块,这是面向对象测试中所特有的模块测试
。 - 模板层
测试一组协同工作的类之间的相互作用,大体上相当于传统软件测试中的集成测试,但是也有面向对象软件的特点【如:对象之间通过发送消息相互作用】。 - 系统层
把各个子系统组装成完整的面向对象软件系统,在组装过程中同时进行测试。
二、 UML(Unified Modeling Language,统一建模语言)
为了统一各种面向对象方法的术语、概念和模型,是面向对象的标准建模语言,通过统一的语义和符号表示,使各种方法的建模过程和表示统一起来,现已成为面向对象建模的工业标准。
1. 事物
(1)结构事物(Structural Thing)
是 UML
模型中的名词,通常是模型的静态部分,描述概念或物理元素,包括:类(Class)、接口(Interface)、协作(Collaboration)、用例(Use
Case)、主动类(Active
Class)、构件(Component)、制品(Artifact)和结点(Node)。
(2)行为事物(Behavior thing)
是 UML
模型的动态部分,是模型中的动词,描述了跨越时间和空间的行为,包括:交互(Interaction)、状态机(State
Machine)和活动(Activity)。
(3)分组事物(Grouping Thing)
是 UML
模型的组织部分,是一些由模型分解成的“盒子”,最主要的分组事物是包(Package)【元素组织成组的机制,这种机制具有多种用途】。
(4)注释事物(Annotational Thing)
是 UML 模型的解释部分,用来描述、说明和标注模型的任何元素。
注解(Note):一种主要的注释事物,是一个依附于一个元素或者一组元素之上,对它进行约束或解释的简单符号。
2. 关系
(1)依赖(Dependency)
是两个事物间的语义关系,其中一个事物(独立事物)发生变化会影响另一个事物(依赖事物)的语义。
(2)关联(Association)
是一种结构关系,描述了一组链,链是对象之间的连接。
聚集(Aggregation):是一种特殊类型的关联,它描述了整体和部分间的结构关系。
(3)泛化(Generalization)
是一种特殊/一般关系,特殊元素(子元素)的对象可替代一般元素(父元素)的对象,子元素共享了父元素的结构和行为。
(4)实现(Realization)
是类元之间的语义关系,其中一个类元指定了由另一个类元保证执行的契约。在两种情况下会使用实现关系:一种是在接口和实现它们的类或构件之间;另一种是在用例和实现它们的协作之间。
3. UML 中的图
(1)类图(Class Diagram)
展现了一组对象、接口、协作和它们之间的关系,给出系统的静态设计视图。静态图
,用于对系统的静态设计视图建模。主要支持系统的功能需求,即系统要提供给最终用户的服务
包含主动类的类图给出了系统的静态进程视图,也可以包含注解和约束,还可以含有包或子系统,二者都用于把模型元素聚集成更大的组块。在面向对象系统的建模中所建立的最常见的图
。
类图中通常包括:类、接口、协作、依赖、泛化和关联关系。
(1) 1 1 :表示一个集合中的一个对象对应另一个集合中一个对象(一对一)。
(2) 0. . ∗ 0..^* :表示一个集合中的一个对象对应另一个集合中的零个或多个对象(可以不对应)。
(3) 1. . ∗ 1..^* :表示一个集合中的一个对象对应另一个集合中的一个或多个对象(至少对应一个)。
(4) ∗ * :表示一个集合中的一个对象对应另一个集合中的多个对象(一对多)。
(2)对象图(Object Diagram)
展现了某一时刻一组对象以及它们之间的关系,为类图的某一快照
。静态图
,在没有类图的前提下,对象图就是静态设计视图。
对象图一般包括:对象和链。
(3)用例图(Use Case Diagram)
展现了一组用例、参与者(Actor)以及它们之间的关系
。静态图
,参与者是人、硬件或其他系统可以扮演的角色;用例是参与者完成的一系列操作
。
用例图通常包括:用例、参与者、用例之间的关系【扩展关系
(
< < e x t e n d > > <<extend>>
)、包含关系
(
< < i n c l u d e > > <<include>>
)、参与者和用例之间的关联关系
,用例与用例以及参与者与参与者之间的泛化关系
】。
(4)交互图
用于对系统的动态方面进行建模。一张交互图表现的是一个交互,由一组对象和它们之间的关系组成,包含它们之间可能传递的消息。可以单独使用,来可视化、详述、构造和文档化一个特定的对象群体的动态方面,也可以用来对一个用例的特定的控制流进行建模。
交互图一般包含:对象、链和消息。
① 序列图(Sequence Diagram)
动态图
,强调消息时间顺序的交互图,是场景(Scenario)的图形化表示,描述了以时间顺序
组织的对象之间的交互活动。
同步消息
【进行阻塞调用,调用者中止执行,等待控制权返回,需要等待返回消息,用实心三角箭头
表示】,异步消息
【发出消息后继续执行,不引起调用者阻塞,也不等待返回消息,用空心三角箭头
表示】,返回消息
【由从右往左的虚线箭头
表示】。
② 通信图(Communication Diagram)
动态图
,也称协作图
,强调接收和发送消息的对象的结构组织的交互图。通信图强调参加交互的对象的组织。产生一张通信图。是顺序图的另一种表示方法,也是由对象和消息组成的图,只不过不强调时间顺序,只强调事件之间的通信,没有固定的画法规则。
首先要将参加交互的对象作为图的顶点,然后把连接这些对象的链表示为图的弧,最后用对象发送和接收的消息来修饰这些链。这就提供了在协作对象的结构组织的语境中观察控制流的一个清晰的可视化轨迹。
③ 交互概览图(Interaction Overview Diagram)
强调控制流的交互图,是活动图的变体,描述业务过程中的控制流概览,软件过程中的详细逻辑概览,以及将多个图进行连接,抽象掉了消息和生命线。使用活动图的表示法,纯粹的交互概览图中所有的活动都是交互发生。
④ 计时图(Timing Diagram)
特别适合实时和嵌入式系统建模的交互图,关注沿着线性时间轴、生命线内部和生命线之间的条件改变。它描述对象状态随着时间改变的情况,很像示波器,适合分析周期和非周期性任务。
(5)状态图(State Diagram)
展现了一个状态机,它由状态、转换、事件和活动组成。关注系统的动态视图,对于接口、类和协作的行为建模尤为重要,强调对象行为的事件顺序。包括简单状态和组合状态、转换(事件和动作)。
可以用状态图对系统的动态方面建模。当对系统、类或用例的动态方面建模时,通常是对反应型对象建模。
转换可以通过事件触发器触发,事件触发后相应的监护条件会进行检查。状态图中状态和转换是两个独立的概念。
以状态为节点,箭线代表触发事件,导致状态的变迁;方框代表状态;实心圆点为起点和终点。
(6)活动图(Activity Diagram)
动态图
,是一种特殊的状态图,它展现了在系统内从一个活动到另一个活动的流程。专注于系统的动态视图,它对于系统的功能建模特别重要,并强调对象间的控制流程。
活动图一般包括:活动状态和动作状态、转换和对象。
一条水平粗线:活动的分岔和汇合线。
每个分岔的分支数代表了可同时运行的线程数。活动图中能够并行执行的是一个分岔粗线下的分支上的活动。
活动图可以表示分支【描述基于布尔表达式的可选择路径,可有一个入流和两个或多个出流,在每个出流上放置一个布尔表达式条件,每个出流的条件不应该重叠,但需要覆盖所有可能性】、合并【描述当两条控制路径重新合并时,不需要监护条件,只有一个出流】、分岔【描述把一个控制流分成两个或多个并发控制流,可以有一个进入转移和两个或多个离去转移,每个离去的转移表示一个独立的控制流,这些流可以并行的进行。汇合】和汇合【表示两个或多个并发控制流的同步,可以有两个或多个进入转移和一个离去转移,意味着每个进入流都等待,直到所有进入流都达到这个汇合处】。
(7)构件图(Component Diagram)
展现了一组构件之间的组织和依赖。静态图
,构件图专注于系统的静态实现视图。与类图相关,通常把构件映射为一个或多个类、接口或协作。
(8)组合结构图(Composite Structure Diagram)
用于描述一个分类器的内部结构,分类器与系统中其他组成部分之间的交互端口,展示一组相互协作的实例如何完成特定的任务,描述设计、架构模式或策略。
(9)部署图(Deployment Diagram)
是用来对面向对象系统的物理方面建模的方法,展现了运行时处理结点以及其中构件(制品)的配置。
静态图
,为系统静态部署视图,部署图物理模块的节点分布
。它与构件图相关,通常一个节点包含一个或多个构件。其依赖关系类似于包依赖,因此部署组件之间的依赖是单向的类似于包含关系
(1) < < a r t i f a c t > > <<artifact>> :表示制品。
(10)包图(Package Diagram)
用于把模型本身组织成层次结构的通用机制,不能执行,展现由模型本身分解而成的组织单元以及其间的依赖关系。
可以拥有其他元素,可以是类、接口、构件、结点、协作、用例和图,甚至是嵌套的其
他包示。
拥有:一种组成关系,是一种按规模来处理问题的重要机制,也意味着元素被声明在包中,一个元素只能被一个包所拥有
,拥有关系的包形成了一个命名空间,其中同一种元素的名称必须唯一。
三、 设计模式
1. 设计模式的要素
- 模式名称(Pattem Name)
一个助记名,它用一两个词来描述模式的问题、解决方案和效果。命名一个新的模式增加了设计词汇。 - 问题(Problem)
描述了应该在何时使用模式。它解释了设计问题和问题存在的前因后果,可能描述了特定的设计问题,也可能描述了导致不灵活设计的类或对象结构。 - 解决方案(Solution)
描述了设计的组成成分、它们之间的相互关系及各自的职责和协作方式。 - 效果(Consequences)
描述了模式应用的效果及使用模式应权衡的问题。
三种模式的概念及其层次关系:
- 架构模式
软件设计中的高层决策,例如 C / S C/S 结构就属于架构模式,架构模式反映了开发软件系统过程中所作的基本设计决策。 - 设计模式
主要关注软件系统的设计,反映了开发软件系统过程中所作的基本设计决策,而设计模式则是主要关注软件系统的设计,与具体的实现语言无关,是在软件开发过程中,经过验证的,用于解决在特定环境下的、重复出现的、特定问题的解决方案。 - 惯用法
最低层的模式,关注软件系统的设计与实现,实现时通过某种特定的程序设计语言来描述构件与构件之间的关系。每种编程语言都有它自己特定的模式,即语言的惯用法。
2. 创建型设计模式
(1)Abstract Factory(抽象工厂)
- 意图
提供一个创建一系列相关或相互依赖对象的接口,而无须指定它们具体的类
。 - 结构
- 适用性
一个系统要由多个产品系列中的一个来配置时。
一个系统要独立于它的产品的创建、组合和表示时。
当提供一个产品类库,只想显示它们的接口而不是实现时。
当要强调一系列相关的产品对象的设计以便进行联合使用时。
(2) Builder(生成器)
- 意图
将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示
。 - 结构
- 适用性
当创建复杂对象的算法应该独立于该对象的组成部分以及它们的装配方式时。
当构造过程必须允许被构造的对象有不同的表示时。
(3)Factory Method(工厂方法)
- 意图
定义一个用于创建对象的接口,让子类决定实例化哪一个类,使一个类的实例化延迟到其子类
。 - 结构
- 适用性
当一个类不知道它所必须创建的对象的类的时候。
当一个类希望由它的子类来指定它所创建的对象的时候。
当类将创建对象的职责委托给多个帮助子类中的某一个,并且你希望将哪一个帮助子类是代理者这一信息局部化的时候。
(4)rototype(原型)
- 意图
用原型实例指定创建对象的种类,并且通过复制这些原型创建新的对象
。 - 结构
- 适用性
当要实例化的类是在运行时刻指定时。
当一个系统应该独立于它的产品创建、构成和表示时。
为了避免创建一个与产品类层次平行的工厂类层次时。
(5)ingleton(单例)
- 意图
保证一个类仅有一个实例,并提供一个访问它的全局访问点
。 - 结构
- 适用性
当类只能有一个实例而且客户可以从一个众所周知的访问点访问它时。
当这个唯一实例应该是通过子类化可扩展的,并且客户无须更改代码就能使用一个扩展的实例时。
3. 结构型设计模式
(1)Adapte(适配器)
- 意图
将一个类的接口转换成客户希望的另外一个接口,使得原本由于接口不兼容而不能一起工作的那些类可以一起工作
。 - 结构
- 适用性
想使用一个已经存在的类,而它的接口不符合要求。
想创建一个可以服用的类,该类可以与其他不相关的类或不可预见的类协同工作。
想使用一个已经存在的子类,但是不可能对每一个都进行子类化以匹配它们的接口,对象适配器可以适配它的父类接口。(仅适用于对象Adapter)
(2)Bridge(桥接)
- 意图
将抽象部分与其实现部分分离,使它们都可以独立地变化
。 - 结构
- 适用性
有许多类要生成的类层次结构。
想对客户完全隐藏抽象的实现部分。(C++)
不希望在抽象和它的实现部分之间有一个固定的绑定关系。
类的抽象以及它的实现都应该可以通过生成子类的方法加以扩充。
对一个抽象的实现部分的修改应对客户不产生影响,即客户代码不必重新编译。
想在多个对象间共享实现(可能使用引用计数),但同时要求客户并不知道这一点。
(3)Composite(组合)
- 意图
将对象组合成树型结构以表示“部分-整体”的层次结构,使得用户对单个对象和组合对象的使用具有一致性。 - 结构
- 适用性
想表示对象的部分-整体层次结构。
希望用户忽略组合对象与单个对象的不同,用户将统一地使用组合结构中的所有对象。
(4)Decorator(装饰)
- 意图
描述了以透明围栏来支持修饰的类和对象的关系,动态地给一个对象添加一些额外的责,从增加功能的角度来看,装饰器模式相比生成子类更加灵活
。 - 结构
- 适用性
处理那些可以撤销的职责。
当不能采用生成子类的方式进行扩充时。
在不影响其他对象的情况下,以动态、透明的方式给单个对象添加职责。
(5)Facade(外观)
- 意图
为子系统中的一组接口提供一个一致的界面,Facade模式定义了一个高层接口,这个接口使得这一子系统更加容易使用
。 - 结构
- 适用性
客户程序与抽象类的实现部分之间存在着很大的依赖性。
需要构建一个层次结构的子系统时,使用Facade模式定义子系统中每层的入口点。
要为一个复杂子系统提供一个简单接口时,子系统往往因为不断演化而变得越来越复杂。
(6)lyweight(享元)
- 意图
运用共享技术有效地支持大量细粒度的对象
。 - 结构
- 适用性
应用程序不依赖于对象标识。
一个应用程序使用了大量的对象。
对象的大多数状态都可变为外部状态。
完全由于使用大量的对象,造成很大的存储开销。
如果删除对象的外部状态,那么可以用相对较少的共享对象取代很多组对象。
(7)Proxy(代理)
- 意图
为其他对象提供一种代理以控制对这个对象的访问,以使得在确实需要这个对象时才对它进行创建和初始化
。 - 结构
- 适用性
虚代理(Virtual Proxy):根据需要创建开销很大的对象。
远程代理(Remote Proxy):为一个对象在不同地址空间提供局部代表。
智能引用(Smart Reference):取代了简单的指针,它在访问对象时执行一些附加操作。
保护代理(Protection Proxy):控制对原始对象的访问,用于对象应该有不同的访问权限的时候。
4. 行为设计模式
(1)Chain of Responsibility(责任链)
- 意图
使多个对象都有机会处理请求,从而避免请求的发送者和接收者之间的耦合关系。将这些对象连成一条链,并沿着这条链传递该请求,直到有一个对象处理它为止
。 - 结构
- 适用性
有多个的对象可以处理一个请求,哪个对象处理该请求运行时刻自动确定。
想在不明确指定接收者的情况下向多个对象中的一个提交一个请求。
可处理一个请求的对象集合应被动态指定。
(2)Command(命令)
- 意图
将一个请求封装为一个对象,从而使得可以用不同的请求对客户进行参数化;对请求排队或记录请求日志,以及支持可撤销的操作
。 - 结构
- 适用性
抽象出待执行的动作以参数化某对象。
在不同的时刻指定、排列和执行请求。
支持取消操作。
(3)Interpreter(解释器)
- 意图
给定一个语言,定义它的文法的一种表示,并定义一个解释器,这个解释器使用该表示来解释语言中的句子
。 - 结构
- 适用性
该文法简单。
效率不是一个关键问题。
当有一个语言需要解释执行,并且可将该语言中的句子表示为一个抽象语法树。
(4)Iterator(迭代器)
- 意图
提供一种方法顺序访问一个聚合对象中的各个元素,且不需要暴露该对象的内部表示
。 - 结构
- 适用性
访问一个聚合对象的内容而无须暴露它的内部表示。
为遍历不同的聚合结构提供一个统一的接口。
支持对聚合对象的多种遍历。
(5)Mediator(中介者)
- 意图
用一个中介对象来封装一系列的对象交互。中介者使各对象不需要显式地相互引用,从而使其耦合松散,而且可以独立地改变它们之间的交互
。 - 结构
- 适用性
一组对象以定义良好但是复杂的方式进行通信,产生的相互依赖关系结构混乱且难以理解。
一个对象引用其他很多对象并且直接与这些对象通信,导致难以复用该对象。
想定制一个分布在多个类中的行为,而又不想生成太多的子类。
(6) Memento(备忘录)
- 意图
在不破坏封装性的前提下捕获一个对象的内部状态,并在对象之外保存这个状态。这样以后就可以将对象恢复到原先保存的状态
。 - 结构
- 适用性
必须保存一个对象在某一个时刻的(部分)状态,这样以后需要时它才能恢复到先前的状态。
如果一个用接口来让其他对象直接得到这些状态,将会暴露对象的实现细节并破坏对象的封装性。
(7)Observer(观察者)
- 意图
定义对象间的一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都得到通知并被自动更新
。 - 结构
- 适用性
当一个抽象模型有两个方面,其中一个方面依赖于另一个方面,将这两者封装在独立的对象中以使它们可以各自独立地改变和复用。
当一个对象必须通知其他对象,而它又不能假定其他对象是谁,即不希望这些对象是紧耦合的。
当对一个对象的改变需要同时改变其他对象,而不知道具体有多少对象有待改变时。
(8)State(状态)
- 意图
允许一个对象在其内部状态改变时改变它的行为,对象看起来似乎修改了它的类
。 - 结构
- 适用性
一个对象的行为决定于它的状态,并且它必须在运行时刻根据状态改变它的行为。
一个操作中含有庞大的多分支的条件语句,且这些分支依赖于该对象的状态。
(9)Strategy(策略)
- 意图
定义一系列的算法,把它们一个个封装起来,并且使它们可以相互替换。此模式使得算法可以独立于使用它们的客户而变化
。 - 结构
- 适用性
许多相关的类仅仅是行为有异。
需要使用一个算法的不同变体。
算法使用客户不应该知道的数据。
一个类定义了多种行为,并且这些行为在这个类的操作中以多个条件语句的形式出现,将相关的条件分支移入它们各自的 Strategy 类中,以代替这些条件语句。
(10)Template Method(模板方法)
- 意图
定义一个操作中的算法骨架,而将一些步骤延迟到子类中,使得子类可以不改变一个算法的结构即可重定义该算法的某些特定步骤
。 - 结构
- 适用性
各子类中公共的行为应被提取出来并集中到一个公共父类中,以避免代码重复。
一次性实现一个算法的不变的部分,并将可变的行为留给子类来实现。
控制子类扩展。
(11)Visitor(访问者)
- 意图
表示一个作用于某对象结构中的各元素的操作。它允许在不改变各元素的类的前提下定义作用于这些元素的新操作
。 - 结构
- 适用性
一个对象结构包含很多类对象,它们有不同的接口,而用户想对这些对象实施一些依赖于其具体类的操作。
需要对一个对象结构中的对象进行很多不同的并且不相关的操作,而又想要避免这些操作“污染”这些对象的类。
定义对象结构的类很少改变,但经常需要在此结构上定义新的操作。