0%

Behavioral Pattern

Chain of Resposibility

  • 收到请求后,每个处理者均对请求进行处理,或者将其传递给链上的下一个处理者
  • 责任链将特定行为转换为_handlers,_而后各责任被摘取成拥有单独方法的类,进而请求沿着这条路检查

结构

structure-indexed.png

特点

  • 可以控制请求处理的顺序
  • 符合单责任原则、开闭原则
  • 一些请求可能最终无法处理

场景

  • 当你的程序期待处理不同种类的请求,用不同方式,但是期待的请求类型和顺序是未知的
  • 当你有必要以特定的顺序执行几个handlers
  • 当handlers和他们的顺序在运行时会改变

Interpreter

解释器模式为某个语言 定义他的语法表示,并定义一个解释器用来处理这个语法

结构

3115781-e3bdbdbe5f35dd9f.webp

  • Context 用来存储解释器上下文环境,包括解释器之外的一些全局信息
  • AbstractExpression 为抽象语法树中的所有节点共享
  • TreminalExpression&NontermialExpression解释器的具体实现
  • client客户

特点

  • 有抽象的父类,便于扩展

  • 可用场景少
  • 复杂文法难以维护

场景

  • 编译器
  • 规则引擎
  • 正则表达式

Command

  • 转换请求称为独立的包含请求相关信息的对象,如此就可以将请求作为方法参数,延迟,排队等

结构

structure-indexed.png
example.png

Invoker Button
Comand Command
Concrete Command copy/cut/paste/undo Command
Receiver Editor
Client Application

特点

  • 解耦出发和执行的操作类(按钮 和 操作,并用命令连接)
  • 开闭原则
  • 实现撤销恢复,延迟执行
  • 将一组简单命令组合成复杂命令

  • 代码会复杂,因为你在发送者和接受者之间增加了一个全新层次

场景

  • 需要通过操作来参数化对象
  • 你想要将操作放入队列中、操作的执行或远程执行操作
  • 希望实现回滚

Iterator

在不暴露底层表现形式的情况下,遍历集合中元素

结构

structure-indexed.png

特点

  • 符合单依职责原则,开闭原则
  • 可以并行遍历同一个集合(迭代器包含自身状态)

  • 如果只有简单的集合,则没有必要
  • 对于某些集合,使用迭代器可能会低效

场景

  • 集合背后为复杂数据结构,希望对客户隐藏(处于便利或安全考虑)
  • 减少重复的 遍历代码
  • 遍历不同甚至无法预知的数据结构

Mediator

减少对象之间混乱无序的依赖关系,限制对象之间的交互,迫使他们通过中介者合作

结构

structure-indexed.png

特点

  • 单一职责原则、开闭原则
  • 减轻应用中多个组件间耦合,可以更方便的复用各个组件

  • 一段时间后中介者可能会演化为上帝对象

场景

  • 一些对象和其他对象紧密耦合导致难以修改
  • 组件因为过于依赖其他组件而无法在不同场景复用
  • 为了能在不同场景下复用一些基本行为,导致你需要大量创建组件子类

Memento

  • 允许不暴露对象实现细节的情况下保存和回复对象之前的状态
  • 建议将对象状态存储在memento的特殊对象中,禁止其他无关对象直接访问memento,必须通过受限的接口与之交互
  1. 对象自己产生历史对象
  2. 严格封装,确保历史不被修改

结构

  • Originator类可以生成自身状态的快照,也可以在需要时通过快照恢复自身状态
  • Memento是原发器状态快照的值对象,通常做法是将备忘录设为不可变的, 并通过构造函数一次性传递数据。
  • **Caretaker(负责人)**仅知道 “何时” 和 “为何” 捕捉原发器的状态,以及何时恢复状态。负责人通过保存备忘录栈来记录原发器的历史状态。 当原发器需要回溯历史状态时, 负责人将从栈中获取最顶部的备忘录, 并将其传递给原发器的恢复 (restoration) 方法。

基于嵌套类基于接口实现
更严格的封装

特点

  • 在不破坏封装的前提下创建对象状态快照
  • 可以通过让Caretaker维护原发器状态历史记录简化Originator

  • 创建过于频繁,将消耗大量内存
  • Caretaker必须完整跟踪原发器声明周期
  • 动态编程语言不能确保备忘录不被修改(PHP、Python)

场景

  • 需要使用快照回复之前的状态
  • 直接访问对象成员变量、获取器等导致的封装破裂

Observer

允许定义一种订阅机制,可以在对象事件发生时候通知多个观察该对象的其他对象

结构

structure-indexed.png

特点

  • 开闭原则
  • 可以在运行时候建立对象之间的联系

  • 订阅者通知的顺序是随机的

场景

  • 当一个对象的状态改变需要改变其他对象,或实际对象是事前位置或动态变化的
  • 当应用中的一些对象必须观察到其他对象时

State

  • 能让对象内部状态发生变化时改变行为,看上去好像类改变了一样

结构

structure-zh-indexed.png

特点

  • 单一职责原则,开闭原则,消除臃肿的状态机条件语句简化上下文

  • 如果状态很少,则会小题大做

场景

  • 对象需要根据自身状态有不同行为,且同时状态数量多且频繁变更
  • 某个类需要根据成员变量值改变自身行为,且大量条件语句
  • 相似状态和基于条件的状态机转换中有许多重复代码

Strategy

让你定义一系列算法,并将他们放入独立的类中,以便于算法对象能相互替换

结构

structure-indexed.png

特点

  • 可以在运行时切换对象内的算法
  • 将算法实现和使用隔离
  • 使用组合代替继承
  • 开闭原则

  • 算法极少改变,没必要引入,会使得程序复杂
  • 客户端必须了解策略间的不同----其需要选择合适的策略
  • 许多现代编程语言都支持函数类型,允许你在一组匿名函数中实现不同版本的算法。如此使用这些函数的方式就和使用策略对象完全相同,无需借助额外的接口

场景

  • 当你想使用对象中各种不同的算法变体,并希望能在运行时切换算法
  • 当你有许多在执行某些行为时略有不同的相似类时
  • 算法在上下文的逻辑不是很重要,如此可以将业务逻辑与具体算法隔离
  • 当类中使用了复杂条件运算符以在同一算法的不同变体中切换

Template

在超类中定义了一个算法框架,允许子类在不修改结构的情况下重写算法特定步骤

结构

structure-indexed.png

特点

  • 你可以允许客户端重写一个大型算法的特定部分,使得算法其他部分修改对其影响很小
  • 将重复代码取到一个超类中

  • 部分客户端收到算法框架限制
  • 通过子类移植默认步骤实现可能违反里氏替换原则
  • 模板方法步骤越多,就越难维护

场景

  • 当你只希望客户端扩展某个特定算法步骤,而不是整个算法
  • 当多个类算法除了有一些细微的不同之外,其他几乎完全一样时

Visitor

将算法和作用的对象隔离
访问者模式建议将新行为放入名为访问者的独立类中,而非整合到已有类中。

结构

structure-zh-indexed.png

特点

  • 开闭原则,单一职责原则
  • 访问者对象可以在各种对象交互时收集一些有用信息

  • 每次元素层次结构中添加或移除一个类,你都要更新所有访问者
  • 在访问者与某个元素交互时,他们可能没有访问元素私有变量的方法和权限

场景

  • 你需要对一个复杂对象结构中的元素执行某些操作
  • 清理辅助行为的业务逻辑
  • 某个行为仅在类惩戒结构中的一些类中有意义,其他类中没意义时

-------------本文结束感谢您的阅读-------------
作者将会持续总结、分享,如果愿意支持作者,作者将会十分感激!!!