本人学习笔记。内容参考《Java设计模式》刘伟 教程配套PPT。仅供学习参考使用。
行为型模式(Behavioral Pattern) 关注系统中对象之间的交互,研究系统在运行时对象之间的相互通信与协作,进一步明确对象的职责。
不仅仅关注类和对象本身,还重点关注它们之间的相互作用和职责划分。
类行为型模式:使用继承关系在几个类之间分配行为,主要通过多态等方式来分配父类与子类的职责。
对象行为型模式:使用对象的关联关系来分配行为,主要通过对象关联等方式来分配两个或多个类的职责。
行为型模式有11种,下面的表格我总结了它们的定义和例子:
模式名称 | 定 义 | 形象化例子 | 应用实例 |
---|---|---|---|
职责链模式 | 将接收请求的对象连接成一条链,并且沿着这条链传递请求,直到有一个对象能够处理它为止。 | 奖学金 | 企业采购的分级审批 |
命令模式 | 将一个请求封装为一个对象,从而让你可以用不同的请求对客户进行参数化,对请求排队或者记录请求日志,以及支持可撤销的操作。 | 电路开关 | 自定义功能键的功能 |
解释器模式 | 给定一个语言,定义它的文法的一种表示,并定义一个解释器,这个解释器使用该表示来解释语言中的句子。 | 语法分析和翻译 | 机器人控制指令表达式 |
迭代器模式 | 提供一种方法顺序访问一个聚合对象中的各个元素,且不用暴露该对象的内部表示。 | 电视遥控器 | 营销管理系统(遍历) |
中介者模式 | 定义一个对象来封装一系列对象的交互。中介者模式使各对象之间不需要显式地相互引用,从而使其耦合松散,而且让你可以独立地改变它们之间的交互。 | 联合国、QQ群 | 客户信息管理窗口 |
备忘录模式 | 在不破坏封装的前提下,捕获一个对象的内部状态,并在该对象之外保存这个状态,这样可以在以后将对象恢复到原先保存的状态。 | 月光宝盒、后悔药 | 中国象棋悔棋 |
观察者模式 | 定义对象之间的一种一对多依赖关系,使得每当一个对象状态发生改变时,其相关依赖对象都得到通知并被自动更新。 | 红绿灯与司机 | 多人联机游戏的联盟系统 |
状态模式 | 允许一个对象在其内部状态改变时改变它的行为。对象看起来似乎修改了它的类。 | 水的固液气 | 银行账户状态转换、倍镜状态 |
策略模式 | 定义一系列算法,将每一个算法封装起来,并让它们可以相互替换,策略模式让算法可以独立于使用它的客户变化。 | 旅游出行方式 | 影票打折方案 |
模板方法模式 | 定义一个操作中算法的框架,而将一些步骤延迟到子类中。模板方法模式使得子类不改变一个算法的结构即可重定义该算法的某些特定步骤。 | 固定流程 | 利息计算模块(流程) |
访问者模式 | 表示一个作用于某对象结构中的各个元素的操作。访问者模式让你可以在不改变各元素的类的前提下定义作用于这些元素的新操作。 | 同一事物不同处理 | 员工数据汇总模块 |
概述
避免将一个请求的发送者与接收者耦合在一起,让多个对象都有机会处理请求。将接收请求的对象连接成一条链,并且沿着这条链传递请求,直到有一个对象能够处理它为止。
客户端无须关心请求的处理细节以及请求的传递,只需将请求发送到链上,将请求的发送者和请求的处理者解耦。
经典例子:奖学金申请层层上交、企业采购的分级审批
结构
其中client要设置责任链,即设置每个具体处理者的下家。
优缺点
优点:
缺点:
概述
将一个请求封装为一个对象,从而让你可以用不同的请求对客户进行参数化,对请求排队或者记录请求日志,以及支持可撤销的操作。
将请求发送者和接收者完全解耦。发送者与接收者之间没有直接引用关系。发送请求的对象只需要知道如何发送请求,而不必知道如何完成请求。
命令模式的本质是对请求进行封装。一个请求对应于一个命令,将发出命令的责任和执行命令的责任分开。
经典例子:电路开关、自定义功能键的功能、可撤销的简易计算器
结构
命令模式包含:Command(抽象命令类)ConcreteCommand(具体命令类)Invoker(调用者)Receiver(接收者)
以自定义功能键功能为例:
实现命令队列:
增加一个CommandQueue类,由该类负责存储多个命令对象,而不同的命令对象可以对应不同的请求接收者。
记录请求日志:
将请求的历史记录保存下来,通常以日志文件(Log File)的形式永久存储在计算机中。可实现恢复机制、批处理、防止请求丢失或重复执行。
实现撤销操作:
可以通过对命令类进行修改使得系统支持撤销(Undo)操作和恢复(Redo)操作。
优缺点
优点:
缺点:
概述
给定一个语言,定义它的文法的一种表示,并定义一个解释器,这个解释器使用该表示来解释语言中的句子。(“语言”是指使用规定格式和语法的代码)
经典例子:语法分析和翻译、机器人控制指令表达式
结构
整体结构可基于抽象语法树。
解释器模式包含:AbstractExpression(抽象表达式)TerminalExpression(终结符表达式)NonterminalExpression(非终结符表达式)Context(环境类)
其中,环境类(Context)用于存储一些全局信息,可用一个哈希表或数组实现,存储一系列公共信息,例如变量名与值的映射关系等,用于在执行具体的解释操作时从中获取相关信息。
优缺点
优点:
缺点:
概述
提供一种方法顺序访问一个聚合对象中各个元素,且不用暴露该对象的内部表示。
将遍历数据的行为从聚合对象中分离出来,封装在迭代器对象中。由迭代器来提供遍历聚合对象内部数据的行为,简化聚合对象的设计,更符合单一职责原则(一个对象应该只包含单一的职责,并且该职责被完整地封装在一个类中)。
经典例子:电视遥控器、 销售管理系统(对商品数据遍历)
结构
迭代器模式包含:Iterator(抽象迭代器)ConcreteIterator(具体迭代器)Aggregate(抽象聚合类)ConcreteAggregate(具体聚合类)
以销售管理系统为例:
其中具体聚合类是商品数据类,具体迭代器是商品迭代器。用迭代器模式设计后,商品数据类只负责存储和管理数据,商品迭代器只负责遍历数据。前者对后者是依赖关系(方法使用另一个类的对象作为参数),后者对前者是关联关系。(复习类之间的关系)
优缺点
优点:
缺点:
概述
定义一个对象来封装一系列对象的交互。中介者模式使各对象之间不需要显式地相互引用,从而使其耦合松散,而且让你可以独立地改变它们之间的交互。
对象之间多对多的复杂关系转化为相对简单的一对多关系。
中介者模式是迪米特法则的一个典型应用。(迪米特法则:每一个软件单位对其他的单位都只有最少的知识,而且局限于那些与本单位密切相关的软件单位)
经典例子:联合国、qq群、客户信息管理窗口
结构
中介者模式包含:Mediator(抽象中介者)ConcreteMediator(具体中介者)Colleague(抽象同事类)ConcreteColleague(具体同事类)
具体中介者继承抽象中介者,具体同事类继承抽象同事类。其中,具体中介者聚合具体同事类;抽象中介者与抽象同事类,后者聚合前者,两者互相依赖。
以客户信息管理窗口为例:
优缺点
优点:
缺点:
概述
在不破坏封装的前提下,捕获一个对象的内部状态,并在该对象之外保存这个状态,这样就可以在以后将对象恢复到原先保存的状态。
提供了一种状态恢复的实现机制,使得用户可以方便地回到一个特定的历史步骤。在很多软件所提供的撤销操作中就使用了备忘录模式。
经典例子:“月光宝盒”、“后悔药”、中国象棋悔棋
结构
备忘录模式包含:Originator(原发器) Memento(备忘录) Caretaker(负责人)
将备忘录类作为原发器类的内部类,使得只有原发器才可以访问备忘录中的数据,其他对象都无法使用备忘录中的数据。
在负责人类中定义一个集合来存储多个备忘录,对集合逆向遍历实现撤销,正向遍历实现重做,从而实现撤销多步操作。以可实现多部撤销的中国象棋软件为例:
优缺点
优点:
缺点:
概述
定义对象之间的一种一对多依赖关系,使得每当一个对象状态发生改变时,其相关依赖对象都得到通知并被自动更新。
发生改变的对象称为观察目标,被通知的对象称为观察者。一个观察目标可以对应多个观察者。
经典例子:红绿灯与驾驶员们、多人联机对战游戏中的联盟系统
结构
观察者模式包含:Subject(目标)ConcreteSubject(具体目标)Observer(观察者)ConcreteObserver(具体观察者)
在目标类中,定义一个观察者集合用于存储所有观察者对象,并通过注册和注销进行增删。在具体目标类中的通知方法中,遍历观察者集合,调用每一个观察者的响应方法。
以多人联机对战游戏中的联盟系统为例:
优缺点
优点:
缺点:
概述
允许一个对象在其内部状态改变时改变它的行为。对象看起来似乎修改了它的类。
用于解决系统中复杂对象的状态转换以及不同状态下行为的封装问题。将一个对象的状态从该对象中分离出来,封装到专门的状态类中,使得对象状态可以灵活变化。
对于客户端而言,无须关心对象状态的转换以及对象所处的当前状态,无论对于何种状态的对象,客户端都可以一致处理。
经典例子:水的固液气三种状态、银行账户状态的转换、屏幕放大镜工具(放大、放大、恢复)
结构
状态模式包含:Context(环境类)State(抽象状态类)ConcreteState(具体状态类)
状态转换的实现:
优缺点
优点:
缺点:
概述
定义一系列算法,将每一个算法封装起来,并让它们可以相互替换。策略模式让算法可以独立于使用它的客户变化。
实现某个目标的途径不止一条,可根据实际情况选择一条合适的途径。策略模式提供了一种可插入式算法的实现方案。
经典例子:交通出行方式、影院售票系统的不同打折方案
结构
策略模式包含:Context(环境类)Strategy(抽象策略类)ConcreteStrategy(具体策略类)
优缺点
优点:
缺点:
概述
定义一个操作中算法的框架,而将一些步骤延迟到子类中。模板方法模式使得子类不改变一个算法的结构即可重定义该算法的某些特定步骤。
是一种基于继承的代码复用技术。将一些复杂流程的实现步骤封装在一系列基本方法中。在抽象父类中提供一个称之为模板方法的方法来定义这些基本方法的执行次序,而通过其子类来覆盖某些步骤,从而使得相同的算法框架可以有不同的执行结果。
经典例子:固定流程(某项具体不一样或空)、利息计算模块(登录、计算、显示)、数据图表显示功能(获取、转换(或无需)、显示)
结构
具体类继承抽象类,并选择性地重写其中某些步骤的方法。
其中某些方法可为钩子方法,即先用“挂钩方法”判断是否需要操作,再实行操作。
优缺点
优点:
缺点:
概述
表示一个作用于某对象结构中的各个元素的操作。访问者模式让你可以在不改变各元素的类的前提下定义作用于这些元素的新操作。
经典例子:对同一事物不同人的不同处理、员工数据汇总模块(不同部门对员工的访问方式不一样)
结构
访问者模式包含:Visitor(抽象访问者)ConcreteVisitor(具体访问者)Element(抽象元素)ConcreteElement(具体元素)ObjectStructure(对象结构)
以员工数据汇总模块为例:
访问者模式与组合模式(组合多个对象形成树形结构,以表示具有部分-整体关系的层次结构)联用:
优缺点
优点:
缺点: