第四篇 行为型设计模式 - 灵活定义对象间交互

简介: 第四篇 行为型设计模式 - 灵活定义对象间交互

行为型设计模式关注对象之间的交互和职责分配,旨在定义对象间的高效、灵活的通信机制。以下是十一种常见行为型设计模式的详解及其应用场景。

1. 策略模式详解及其应用场景

详解:

策略模式定义了一系列算法,并将每一个算法封装起来,使它们可以互相替换。策略模式让算法的变化独立于使用该算法的客户。

在策略模式中,通常包含以下角色:

  • Strategy(策略)接口:声明所有支持的算法的公共操作。
  • Concrete Strategy(具体策略)类:实现 Strategy 接口,提供具体的算法实现。
  • Context(上下文)类:持有一个 Strategy 对象引用,使用这个策略来执行相关操作。

应用场景:

策略模式适用于以下场景:

  • 当一个系统需要在多种算法中进行选择时,如排序算法、数据加密等。
  • 当如果更换或增加新的算法,不希望修改客户端代码时。

例如,在电商系统中,可以根据不同的促销策略创建多个具体策略类,上下文根据用户选择的策略应用相应的优惠算法。

2. 模板方法模式详解及其应用场景

详解:

模板方法模式在一个抽象类中定义一个操作中的算法骨架,而将一些步骤延迟到子类中实现。它使得子类可以在不改变结构的情况下重写部分算法。

在模板方法模式中,通常包含以下角色:

  • Abstract Class(抽象类):定义了一个或多个操作的固定步骤以及可变步骤的模板方法。
  • Concrete Class(具体类):继承自抽象类,实现父类中定义的抽象方法,完成算法的一部分。

应用场景:

模板方法模式适用于以下场景:

  • 当多个类有相同的算法结构,但各自的具体实现不同时。
  • 当希望为子类提供一个统一的操作框架,且这些操作大部分是固定的,但某些步骤允许子类自定义时。

例如,在咖啡制作过程中,抽象咖啡类定义了煮咖啡的基本流程(加水、加热、冲泡),而美式咖啡类和拿铁咖啡类则分别实现添加咖啡粉和奶泡这两个可变步骤。

3. 观察者模式详解及其应用场景

详解:

观察者模式定义了对象之间的一对多依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都会得到通知并自动更新。

在观察者模式中,通常包含以下角色:

  • Subject(主题/被观察者)接口或抽象类:维护一个观察者列表,并定义添加、删除观察者的方法,以及通知所有观察者的接口。
  • Concrete Subject(具体主题/具体被观察者)类:实现了 Subject,当其状态改变时负责通知所有注册过的观察者。
  • Observer(观察者)接口:定义了当主题状态变化时更新自己的方法。
  • Concrete Observer(具体观察者)类:实现了 Observer 接口,存储对 Concrete Subject 的引用,并在其状态改变时进行响应。

应用场景:

观察者模式适用于以下场景:

  • 当一个对象的改变需要同时改变其他对象,而且不知道具体有多少对象需要被改变时。
  • 当一个对象必须通知其他对象,而并不希望指定这些对象及如何通知它们时。

例如,在气象预报系统中,天气数据作为被观察者,而各种接收设备(如手机APP、网页展示等)作为观察者,当天气数据发生变化时,会自动通知所有订阅了天气数据的服务。

4. 迭代器模式详解及其应用场景

详解:

迭代器模式提供了一种方法顺序访问一个聚合对象的各个元素,而又不暴露其内部的表示。

在迭代器模式中,通常包含以下角色:

  • Iterator(迭代器)接口:定义获取下一个元素、检查是否还有元素的方法。
  • Concrete Iterator(具体迭代器)类:实现 Iterator 接口,遍历集合中的元素。
  • Aggregate(聚合)接口:定义创建迭代器对象的方法。
  • Concrete Aggregate(具体聚合)类:实现 Aggregate 接口,存储元素并返回对应的迭代器实例。

应用场景:

迭代器模式适用于以下场景:

  • 需要对容器内的元素进行顺序访问或随机访问,而又不希望暴露容器的内部结构时。
  • 在处理一组相似类型的对象时,能够提供一致的访问方式。

例如,在Java Collection Framework中,ArrayList、LinkedList等集合类都提供了迭代器,用于遍历集合中的元素。

5. 责任链模式详解及其应用场景

详解:

责任链模式使多个对象都有机会处理请求,避免请求发送者与接收者之间的耦合关系。请求沿着链传递,直到被正确处理为止。

在责任链模式中,通常包含以下角色:

  • Handler(处理器)接口或抽象类:定义处理请求的接口,包含指向下一个处理器的引用。
  • Concrete Handler(具体处理器)类:实现 Handler,能够处理特定的请求,也可以将请求转发给下一个处理器。

应用场景:

责任链模式适用于以下场景:

  • 多个对象可能需要处理同一请求,但是哪个对象处理请求由运行时决定。
  • 请求处理者以及它们之间的关系应当能够在运行时动态地重新配置。

例如,在企业审批流程中,每个审批节点都是一个处理器,根据请求内容的不同,请求从一个节点流向另一个节点,直至找到有权批准该请求的节点。

6. 命令模式详解及其应用场景

详解:

命令模式将请求封装为一个对象,使得可以用不同的请求对客户进行参数化;可以对请求排队或者记录请求日志,以及支持可撤销的操作。

在命令模式中,通常包含以下角色:

  • Command(命令)接口:声明执行命令的方法。
  • Concrete Command(具体命令)类:实现 Command 接口,绑定接收者并调用其操作。
  • Receiver(接收者)类:知道如何实施和执行一个请求相关的操作。
  • Invoker(调用者)类:要求命令对象执行请求。

应用场景:

命令模式适用于以下场景:

  • 需要在不同的时间点执行请求,或者将请求放入队列中。
  • 需要支持命令的撤销操作。
  • 将动作与动作的发起者解耦,使得发起者不必了解接收者细节。

例如,在图形用户界面中,按钮点击事件可以作为一个命令对象,点击后通过调用者触发命令执行,同时支持撤销操作。

7. 备忘录模式详解及其应用场景

详解:

备忘录模式在不破坏封装性的前提下,捕获一个对象的内部状态,并在该对象之外保存这个状态。这样以后就可将对象恢复到原先保存的状态。

在备忘录模式中,通常包含以下角色:

  • Originator(原发器)类:拥有一个复杂状态的对象,能够创建并恢复备忘录数据。
  • Memento(备忘录)类:存储 Originator 的内部状态,但对外部世界隐藏这些状态的具体信息。
  • Caretaker(管理者)类:持有备忘录对象,但不能对其内容进行操作,只负责保存和恢复。

应用场景:

备忘录模式适用于以下场景:

  • 需要保存和恢复对象的复杂状态,以便撤销操作或回滚到历史状态。
  • 需要在不影响对象本身的情况下保存对象状态。

例如,在文本编辑器中,可以利用备忘录模式保存文档的各个版本,方便用户随时撤销或恢复到某个历史版本。

8. 状态模式详解及其应用场景

详解:

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

在状态模式中,通常包含以下角色:

  • Context(环境)类:维护一个当前状态对象的引用,并将与状态有关的行为委托给当前状态对象。
  • State(状态)接口:定义所有具体状态类都要实现的接口。
  • Concrete State(具体状态)类:每个具体状态类对应一个状态,实现 State 接口,负责处理与当前状态相关的业务逻辑。

应用场景:

状态模式适用于以下场景:

  • 一个对象的行为取决于它的状态,并且它必须在运行时根据状态改变其行为。
  • 避免使用大量的条件语句判断对象的状态。

例如,在ATM机中,账户状态(正常、冻结、透支等)会影响账户的取款、存款等功能,每种状态对应一个具体状态类,根据账户状态执行相应操作。

9. 访问者模式详解及其应用场景

详解:

访问者模式表示一个作用于某对象结构中的各元素的操作。它使你可以在不改变各元素类的前提下定义作用于这些元素的新操作。

在访问者模式中,通常包含以下角色:

  • Visitor(访问者)接口:声明访问者可以访问哪些元素以及访问的结果是什么。
  • Concrete Visitor(具体访问者)类:实现了 Visitor 接口,定义对每个元素类的具体操作。
  • Element(元素)接口:声明接受 Visitor 的方法,一般为 accept(Visitor visitor)。
  • Concrete Element(具体元素)类:实现 Element 接口,具体存储数据,并调用访问者的方法。

应用场景:

访问者模式适用于以下场景:

  • 需要在不改变现有类的基础上扩展功能,即需要对一个复杂的对象结构中的元素进行很多不同操作时。
  • 对象结构中元素的类比较稳定,但其操作算法易变或者可能有许多不同的操作算法。

例如,在编译器设计中,可以定义一个抽象语法树(AST),节点代表源代码的不同部分。访问者模式可以用来实现类型检查、代码优化、错误检测等多种独立的遍历和处理逻辑,每种逻辑对应一个具体的访问者类。

10. 中介者模式详解及其应用场景

详解:

中介者模式用一个中介对象来封装一系列的对象交互,使原本直接关联的对象解耦,使得各对象之间不需要显式地相互引用,而是通过中介对象间接通信。

在中介者模式中,通常包含以下角色:

  • Mediator(中介者)接口或抽象类:定义了同事对象与中介者之间的交互方式。
  • Concrete Mediator(具体中介者)类:实现了 Mediator 接口,负责协调各个同事对象之间的交互行为。
  • Colleague(同事)类:定义同事对象,它们只知道中介者而不知道其他同事对象,通过调用中介者的方法与其他同事对象通信。

应用场景:

中介者模式适用于以下场景:

  • 多个对象之间存在复杂的依赖关系,导致系统难以理解和维护。
  • 当需要简化多个对象间的通信复杂性,降低耦合度时。

例如,在GUI框架中,事件调度器(如Java Swing中的Event Dispatch Thread)作为中介者,协调按钮、文本框等各种组件之间的事件传递和响应。

11. 解释器模式详解及其应用场景

详解:

解释器模式提供了一种用于表示可计算语句的语法表示,并定义了一个解释器来解释该表示并执行相应的运算。

在解释器模式中,通常包含以下角色:

  • AbstractExpression(抽象表达式)接口或抽象类:声明解释操作的公共接口,为所有具体表达式类提供统一的操作入口。
  • TerminalExpression(终结符表达式)类:实现抽象表达式接口,对应文法中的终端符号,通常直接产生结果。
  • NonterminalExpression(非终结符表达式)类:同样实现抽象表达式接口,对应文法中的非终结符,通常包含对其他子表达式的引用并进行组合运算。
  • Context(上下文)类:存储解析过程中所需的信息,为解释器提供运行环境。

应用场景:

解释器模式适用于以下场景:

  • 有一个简单的语言需要解释,且语言的规则相对固定且易于建模。
  • 可以将特定领域的问题抽象为一种语言或表达式,且需求是开发能够解释这种语言的解释器。

例如,在SQL查询解析器中,可以使用解释器模式将SQL语句转换成内部数据结构,然后进行查询操作。

12. 综述

通过以上对行为型设计模式的详解和应用场景分析,我们可以看到这些模式都致力于解决对象间交互和职责分配的问题,帮助开发者更好地组织程序结构,提高代码复用性和灵活性。在实际项目中灵活运用这些模式,有助于构建出更加健壮、易于维护和扩展的软件系统。

相关文章
|
20天前
|
设计模式
**工厂模式与抽象工厂模式**都是创建型设计模式,用于封装对象创建,减少耦合
【6月更文挑战第23天】**工厂模式与抽象工厂模式**都是创建型设计模式,用于封装对象创建,减少耦合。工厂模式专注于单个对象,通过具体工厂创建具体产品,适用于简单对象创建;抽象工厂则关注一系列相关产品,提供创建一族对象的接口,适用于处理多个不兼容产品族。选择模式基于问题域的复杂性,单个产品需求时用工厂模式,多产品族时用抽象工厂模式。
16 5
|
3天前
|
设计模式 安全 Java
Java面试题:设计模式如单例模式、工厂模式、观察者模式等在多线程环境下线程安全问题,Java内存模型定义了线程如何与内存交互,包括原子性、可见性、有序性,并发框架提供了更高层次的并发任务处理能力
Java面试题:设计模式如单例模式、工厂模式、观察者模式等在多线程环境下线程安全问题,Java内存模型定义了线程如何与内存交互,包括原子性、可见性、有序性,并发框架提供了更高层次的并发任务处理能力
15 1
|
16天前
|
设计模式 缓存 Java
Java设计模式:享元模式实现高效对象共享与内存优化(十一)
Java设计模式:享元模式实现高效对象共享与内存优化(十一)
|
23天前
|
设计模式 算法
行为型设计模式之模板模式
行为型设计模式之模板模式
|
16天前
|
设计模式 Java 数据库
Java设计模式:桥接模式实现灵活组合,超越单一继承的设计之道(十)
Java设计模式:桥接模式实现灵活组合,超越单一继承的设计之道(十)
|
23天前
|
设计模式 存储
行为型设计模式之观察者模式
行为型设计模式之观察者模式
|
23天前
|
设计模式 算法
行为型设计模式
行为型设计模式
|
2月前
|
设计模式 Java API
【设计模式】JAVA Design Patterns——Active Object(活动对象设计模式)
【设计模式】JAVA Design Patterns——Active Object(活动对象设计模式)
|
4天前
|
设计模式 Go
Go语言设计模式:使用Option模式简化类的初始化
在Go语言中,面对构造函数参数过多导致的复杂性问题,可以采用Option模式。Option模式通过函数选项提供灵活的配置,增强了构造函数的可读性和可扩展性。以`Foo`为例,通过定义如`WithName`、`WithAge`、`WithDB`等设置器函数,调用者可以选择性地传递所需参数,避免了记忆参数顺序和类型。这种模式提升了代码的维护性和灵活性,特别是在处理多配置场景时。
41 8
|
12天前
|
设计模式 JavaScript 前端开发
js设计模式【详解】—— 构造函数模式
js设计模式【详解】—— 构造函数模式
18 6