设计模式-可复用面向对象软件的基础读书笔记-行为型模式

行为模式

行为模式涉及到算法和对象间职责的分配
行为模式不仅描述对象或类的模式 还描述他们之间的通信模式
这些模式刻画了在运行时难以跟踪的复杂的控制流 将你的注意力从控制流转移到对象之间的联系上来


Chain of Responsibility 职责链

意图

使多个对象都有机会处理请求 从而避免请求的发送者和接受者之间的耦合关系
将这些对象连成一条链并沿着这条链传递该请求直到有一个对象处理他

适用性

  1. 有多个对象可以处理一个请求 哪个对象处理该请求运行时自动确定
  2. 你想在不明确指定接受者的情况下 向多个对象中的一个提交一个请求
  3. 可处理一个请求的对象集合应该被动态指定

结构图

在这里插入图片描述
效果

  1. 降低耦合
  2. 增强了给对象指派职责的灵活性
  3. 不保证被请求被接受处理

效果

  1. 客户端提交一个请求时 将沿请求链传递直至一个ConcreteHandle对象负责处理它

实现

  1. 实现后继者链
  2. 连接后继者
  3. 表示请求
    3.1 请求是一个硬编码的操作调用 这很垃圾
    3.2 使用一个处理函数 函数以一个请求码为参数
    3.3 请求可以封装为一个独立的Request对象
    为了标识这是一个什么请求 可以给Request定义一个访问器(accessor)以返回该请求的标识符

相关模式

  1. 常与Composite模式一起使用 在这种情况下 一个构件的父部件可以作为他的后继

Command 命令

意图

将一个请求封装为一个对象 从而使你可用不同的请求对客户进行参数化 比如对请求进行排队或记录日志或支持可撤销操作

适用性

  1. 抽象出待执行的动作以参数化某对象 可以用过程语言中的回调函数表达这种参数化机制
    Command模式是回调机制的一个面向对象的产品
  2. 在不同的时刻 指定 排列和执行 一个请求
    一个Command对象可以有一个与初始请求无关的生存周期
    比如一个请求与地址的接收者与地址空间无关 就可以将该请求传递到另一个进程处理
  3. 支持取消操作 可以保存execute之前的状态然后unexecute
  4. 支持修改日志
  5. 等等

结构图

在这里插入图片描述
协作

  1. Client创建一个具体的对象并设定他的接收者

  2. Invoker 存储该Command对象

  3. Invoker 通过调用Command的execute来提交一个请求
    在这里插入图片描述
    实现

  4. …等等

  5. 使用c++模版可以避免为每一种动作和接收者都创建一个Command子类

相关模式

  1. Composite模式可以被用来实现宏命令
  2. Memento模式可以用来保持某个状态 用来支持命令的取消
  3. …等等

Interpreter 解释器

意图

给定一个语言 定义他的文法的一种表示 并定义一个解释器 这个解释器使用该表示来解释语言中的句子

动机

如果一个特定类型的问题发生的频率足够高 那么可能就值得将该问题的各个实例表述为一个简单语言中的句子
这样就可以构件一个解释器 该解释器通过解释这些句子来解决该问题

结构图
这图我看起来就觉得像是一个Composite的模式

在这里插入图片描述
相关模式

  1. Composite: 抽象语法树是一个复合模式的实例
  2. Flyweight: 说明了如何在抽象语法树中共享TerminalExpression
  3. Iterator: 解释器可用一个迭代器遍历该结构
  4. Visitor: 可以用来在一个类中维护抽象语法树的各节点的行为

Iterator 迭代器

意图

提供一种方法顺序访问一个聚合对象中的各个元素 而又不需要暴露该对象的内部表示

结构图

aaaa
实现

  1. 很多自己翻阅书籍 哈

Mediator 中介者

意图

用一个中介对象来封装一系列的对象的交互 中介者使各个对象不需要显示的互相引用 从而使其耦合松散 可以独立的改变他们之间的交互

动机

面向对象鼓励将各个行为分布到各个对象中 这种分布可能会导致对象间有许多连接在最坏的情况下每一个对象都知道其他的所有对象 可以通过将一系列行为封装在一个单独的中介者中来避免这个问题 这里看起来有些像Facade

结构图

在这里插入图片描述
协作

同事向一个中介者对象发送消息和接收请求 中介者对象在各个同事之间适当的转发请求以实现协作行为

效果

  1. 减少子类生成
  2. Colleague解耦
  3. 简化了对象协议
  4. 对对象之间的协作进行了抽象
  5. 使控制集中化 但这也是问题所在 但这也是问题所在 但这也是问题所在
    中介者模式将交互的复杂性变为中介者的复杂性 中介者过于复杂时可能会抵消该模式带来的好处

实现

  1. 当一个感兴趣的事情发生时 Colleague必须与其Mediator进行通信
    一般使用Observer模式 或者在变化时调用一个Mediator的一个特殊通知接口 比如OnxxxChanged等等

相关模式

  1. Facade与中介者模式的不同在于 Facade是对一个对象子系统进行抽象 从而提供更为方便的接口 协议是单向的即
    Facade对这个子系统类提出请求 但反之则不行
    Mediator提供了个Colleague对象不支持或者不能协作的行为而且协议是多向的
  2. Colleague可以使用Observer模式与Mediator通信

Memento 备忘录

意图

在不破坏封装的前提下 捕获一个对象的内部状态 并在该对象外保存在状态 这个就可以在以后恢复这个对象到之前的状态

适用性

  1. 保存一个对象在某个时刻的部分状态 可以在以后需要时进行恢复
  2. 如果用一个接口来让其他对象直接得到这些状态 将会保留对象的实现细节并破会对象的封装性

结构图

在这里插入图片描述
协作

Caretaker

  • 负责保存备备忘录 不能对备忘录的内容进行操作或检查

Originator

  • 原发器创建备忘录或者用备忘录恢复

Memento

  • 存储原发器的内部状态
  • 一个只有Caretaker看到的窄接口 他只能将备忘录传递给其他对象
  • 一个只有原发器的宽接口 允许访问返回到先前状态的所有数据

管理器向原发器请求一个备忘录 保留一段时间 然后返回给原发器 交互图如下
在这里插入图片描述

效果

  1. 保持封装的边界
  2. 简化了原发器
  3. 使用备忘录的代价可能较高 可能需要拷贝大量数据
  4. 定义上说的宽窄接口
  5. 维护备忘录的潜在代价

实现

  1. 语言支持
  2. 存储增量式改变

相关模式

  1. Command可以用Memento来支持可撤销操作
  2. Iterator备忘录可以用于迭代

Observer 观察者

意图

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

动机

将一个系统分割成一系列互相协作的类有一个常见的副作用 维护相关对象的一致性
Observer是一种订阅发布模式

结构图

在这里插入图片描述
效果和实现

  1. …这个就不在具体描述了 这里着重一点 封装复杂的更新语义 可以称这个对象为更改管理器 目的是减少观察者反映其目标状态变化的工作量 重要的是 一个操作设计到几个相互依赖的目标进行改动 就必须在所有的目标都完成改动后才一次性通知

相关模式

  1. Mediator 通过封装复杂的更新语义 ChangeManager 充当目标和观察者之间的中介者
  2. Singleton ChangeManager可以使用单件模式

State 状态

意图

允许一个对象在其内部状态改变时改变它的行为 对象看起来似乎是修改了他的类

适用性

  1. 对象的行为取决于他的状态 并且必须在运行时刻根据状态改变他的行为
  2. 一个操作中有大量的分支条件语句依赖于该对象的状态

结构图

在这里插入图片描述
实现

  1. 谁定义状态转换 如果转换规则是固定的 那么可以在Context中实现 然而让State子类自身指定他们的后继状态已经合适进行转换 往往更加灵活 不过这样的话需要在Context中增加一个接口让State显示的设定Context的当前状态 这种方法还一个缺点 一个State至少拥有了另一个子类的信息 在子类的实现之间产生了依赖-------------------我貌似更喜欢在state中指定后继
  2. 创建和销毁state第一种需要时创建并随后销毁第二种提前创建不销毁
  3. …等等

相关模式
4. Flyweight 解释了何时以及如何共享状态
5. 状态对象通常都是Singleton


Strategy 策略

意图

定义一系列的算法 把他们一个个封装起来 并且使他们可以互换 本模式可以使算法可以独立于他的客户变化

结构图

这结构图 看起来就是一个 看起来就是一个 看起来就是一个 用一个委托的组合方式代替继承

在这里插入图片描述
协作

  1. context将请求转发给strategy 并且客户通常创建一个ConcreteStrategy给Context

效果

  1. 相关算法系列
  2. 一个代替继承的方法 比如不这样的话 其中一种方法是继承Context
  3. 消除了一些条件语句 比如不这样的话 可以通过一些if进行不用的操作
  4. 实现的选择有了多样选择性
  5. 问题1 客户必须了解strategy的去呗
  6. 问题2 Strategy与Context的通信开销 因为简单的ConcreteStrategy可能永远不会用到客户端传递过来的参数信息
  7. 问题3 增加了对象数目(Strategy) 可以用Flyweight来稍微减轻这影响

实现

  1. 定义Strategy和Context接口
  2. 可以将Strategy当做模板参数
  3. Strategy可以使可选的 没有的话可以执行缺省默认行为

相关模式
4. Flyweight Strategy对象通常是很好的轻量级对象


Template Method 模版方法

意图

定义一个操作中算法的骨架 而将一些步骤延迟到子类中 Template Method 使得子类可以不改变一个算法的结构就可以重定义这个算法中的某些特定步骤

适用性

  1. ......其他不描述
  2. 可以控制子类扩展 只允许在某些特定的点进行扩展

结构图

在这里插入图片描述

效果

  1. 模板方法导致一种反向的控制结构 这种结构称为好莱坞原则 即 "别找我们 我们找你"
    这里指的是父类调用子类的操作 而不是相反
  2. 也可以拿来做钩子操作
  3. ......等等

相关模式

  1. Factory Method 常被模板方法调用
  2. Strategy 模版方法使用继承来改变算法的一部分 Strategy使用委托来改变整个算法

Visitor 访问者

意图

表示一个作用于某个对象结构中的各元素的操作 他可以使在不改变元素的类的前提下定义对这些元素的新操作

动机

使用Visitor模式 必须定义两个层次的类 一个对应于接受操作的元素Node层次 另一个对应于定义对元素的操作的访问者NodeVisitor层次
给访问者层次类增加一个新类就可以创建一个新的操作

结构图

在这里插入图片描述
参与者

  1. ObjectStructure 对象结构 就是在意图中说的那个包含很多对象的对象

协作

  1. 一个使用Visitor模式的客户必须创建一个ConcreteVisitor对象 然后遍历该对象结构并用该访问者访问每一个元素
  2. 当一个元素被访问时 它调用对应于它的Visitor操作 如果必要 可以将元素自身传递给Visitor以便访问元素状态

在这里插入图片描述

效果

  1. 易于增加新操作
  2. 访问者集中相关的操作而分离无关的操作
  3. 问题1新增Element比较困难 需要在Visitor中添加相关操作 哈
  4. 通过类层次进行访问
  5. 累积状态
  6. 问题2破坏封装 访问者假定ConcreteElement功能足够强 足可以让访问者进行他的工作
    那么该模式常常迫使你提供访问元素内部状态的公有操作而导致破坏封装

实现

  1. 双分派 自行查阅书籍
  2. 谁负责遍历对象结构 一个访问者必须访问这个对象结构的每一个元素 遍历的职责有以下三个地方可以处理
    2.1 对象结构中
    2.2 访问者中
    2.3 或一个独立的迭代器Iterator

相关模式

  1. Composite 访问者可以用于对一个有Composite模式定义的对象结构进行操作
  2. Interpret 访问者可以用于解释

嚯哈 没了

发布了32 篇原创文章 · 获赞 0 · 访问量 1515

猜你喜欢

转载自blog.csdn.net/u010571102/article/details/103919468