当前位置: 首页 > news >正文

持续总结中!2024年面试必问 20 道设计模式面试题(七)

上一篇地址:持续总结中!2024年面试必问 20 道设计模式面试题(六)-CSDN博客

十三、状态模式(State Pattern)和策略模式(Strategy Pattern)有何区别?

状态模式(State Pattern)和策略模式(Strategy Pattern)都是行为型设计模式,它们提供了不同的方法来处理对象的行为变化。以下是两种模式的主要区别:

状态模式(State Pattern):

状态模式允许一个对象在其内部状态改变时改变它的行为,看起来好像改变了其类。它主要用于实现状态机,即行为随状态改变而变化的场景。

特点:

  • 状态模式关注对象的状态以及状态之间的转换。
  • 状态模式通常用于封装复杂的条件语句(如基于状态的 if-else 或 switch-case 语句)。

组成部分:

  • 状态接口(State):定义了所有具体状态共有的行为。
  • 具体状态(Concrete State):实现状态接口,定义具体的状态行为和状态转换逻辑。
  • 上下文(Context):维护当前状态,并提供给客户端使用。

使用场景:

  • 当一个对象的行为依赖于它的状态,并且状态在运行时会改变时。

策略模式(Strategy Pattern):

策略模式定义了一系列算法,并将每一个算法封装起来,使它们可以互换,算法的变化不会影响到使用算法的客户。

特点:

  • 策略模式关注算法或行为的家族,以及它们之间的互换性。
  • 策略模式通常用于替代复杂的条件语句,通过定义一系列的策略来实现行为的变化。

组成部分:

  • 策略接口(Strategy):定义了所有策略共有的接口。
  • 具体策略(Concrete Strategy):实现策略接口,定义具体的算法或行为。
  • 上下文(Context):配置一个策略对象,通过这个策略对象来执行算法。

使用场景:

  • 当需要在运行时选择使用不同的算法或行为时。

状态模式与策略模式的区别:

  1. 关注点不同

    • 状态模式关注的是对象的状态以及状态之间的转换。
    • 策略模式关注的是算法或行为的家族,以及它们之间的互换性。
  2. 使用目的不同

    • 状态模式用于根据对象的状态来改变行为,实现状态机。
    • 策略模式用于在运行时根据不同的策略来改变行为,实现算法的动态选择。
  3. 状态与策略的区别

    • 状态通常与对象的属性或环境有关,而策略通常与解决问题的方法有关。
  4. 上下文的不同

    • 在状态模式中,上下文维护一个状态对象,该状态对象决定了对象的行为。
    • 在策略模式中,上下文维护一个策略对象,该策略对象定义了对象的行为。
  5. 变化频率不同

    • 状态模式中的状态转换通常是由于对象的属性或环境发生变化。
    • 策略模式中的策略变化通常是由于外部条件或用户选择。
  6. 实现方式不同

    • 状态模式通常通过状态对象来封装状态转换逻辑。
    • 策略模式通常通过策略对象来封装算法或行为。
  7. 可扩展性不同

    • 状态模式在添加新状态时可能需要修改上下文类,因为状态转换逻辑可能依赖于上下文。
    • 策略模式在添加新策略时不需要修改上下文类,因为策略是独立的,上下文只是使用策略。

总结来说,状态模式和策略模式虽然都可以改变对象的行为,但它们的关注点、使用目的、实现方式和可扩展性都有所不同。状态模式适用于行为随状态变化的场景,而策略模式适用于需要在运行时动态选择算法或行为的场景。

十四、请描述备忘录模式(Memento Pattern)及其使用场景。

备忘录模式(Memento Pattern),也称为备忘录对象模式,是一种行为设计模式,用于在不破坏封装性的前提下,捕获并保存一个对象的内部状态,以便之后可以恢复该状态。

备忘录模式的组成部分:

  1. 发起人(Originator):负责创建一个备忘录,用以记录当前对象的状态,并且可以恢复到先前的状态。
  2. 备忘录(Memento):存储发起人对象的内部状态,并且可以防止其他对象访问这些状态。
  3. 负责人(Caretaker):负责保存备忘录,但是不能对备忘录内容进行操作或检查。

备忘录模式的工作原理:

  1. 发起人对象在关键的时刻创建一个备忘录对象,将自身的状态存储在其中。
  2. 发起人对象可以继续变化,备忘录对象保存了创建时刻的状态。
  3. 当需要恢复到之前的状态时,发起人对象可以从备忘录对象中读取之前的状态信息,恢复到那个状态。

备忘录模式如何使用:

  • 创建备忘录:发起人对象在关键状态时创建一个备忘录。
  • 保存备忘录:负责人对象保存这个备忘录,可能将其存储在列表或其他结构中。
  • 恢复状态:当需要回退到之前的状态时,发起人对象从负责人那里获取备忘录,并恢复其状态。

使用场景:

备忘录模式特别适用于以下情况:

  • 当需要提供一个可以恢复到之前状态的功能,比如“撤销”操作。
  • 当不希望外界直接获取对象的内部状态,同时又需要保存对象的状态时。
  • 当对象的当前状态占用大量资源,而通过备忘录可以减少资源消耗时。

代码示例(伪代码):

// 备忘录接口
class Memento {private String state;public Memento(String state) {this.state = state;}public String getState() {return state;}
}// 发起人
class Originator {private String state;public void setState(String state) {this.state = state;}public String getState() {return state;}public Memento saveStateToMemento() {return new Memento(state);}public void getStateFromMemento(Memento memento) {state = memento.getState();}
}// 负责人
class Caretaker {private List<Memento> mementoList = new ArrayList<>();public void addMemento(Memento memento) {mementoList.add(memento);}public Memento getMemento(int index) {return mementoList.get(index);}
}// 客户端代码
Originator originator = new Originator();
Caretaker caretaker = new Caretaker();originator.setState("State 1");
caretaker.addMemento(originator.saveStateToMemento());originator.setState("State 2");
// ... 其他操作 ...// 撤销到之前的状态
originator.getStateFromMemento(caretaker.getMemento(0));
// originator 的状态现在是 "State 1"

在这个示例中,Originator 类负责创建备忘录,并可以保存和恢复状态。Memento 类负责存储状态信息。Caretaker 类负责保存备忘录对象,可以管理多个备忘录,例如实现撤销栈。客户端代码通过使用这些类来实现状态的保存和恢复。通过这种方式,备忘录模式提供了一种在不破坏封装性的情况下保存和恢复对象状态的方法。

相关文章:

  • ElasticSearch(ES)
  • 基于detours的Windows Hook
  • 每天五分钟计算机视觉:如何在现有经典的卷积神经网络上进行微调
  • 阿里云 app 备案 获取公钥和md5
  • OS复习笔记ch11-3
  • 1. zabbix监控服务器部署
  • 高性价比MOS推荐:惠海HC090N10L,HC025N10L,100V高耐压,12V/24V加湿器和3.7V打火机专用MOS
  • JAVAEE之网络原理(2)_传输控制协议(TCP)的连接管理机制,三次握手、四次挥手,及常见面试题
  • PHP转Go系列 | 字符串的使用姿势
  • 初阶 《数组》 1. 一维数组的创建和初始化
  • Github 2024-06-19 开源项目日报 Top10
  • 什么是RPA
  • 【王树森】深度强化学习(DRL)学习笔记
  • 系统安全(补充)
  • 【Linux】CentOS 7 安装配置 postfix 邮件服务器随笔
  • 实现windows 窗体的自己画,网上摘抄的,学习了
  • 【node学习】协程
  • Apache Pulsar 2.1 重磅发布
  • nginx(二):进阶配置介绍--rewrite用法,压缩,https虚拟主机等
  • NLPIR语义挖掘平台推动行业大数据应用服务
  • python学习笔记 - ThreadLocal
  • vue+element后台管理系统,从后端获取路由表,并正常渲染
  • 关于 Linux 进程的 UID、EUID、GID 和 EGID
  • 汉诺塔算法
  • 前端之Sass/Scss实战笔记
  • 微服务框架lagom
  • 小程序开发中的那些坑
  • 一份游戏开发学习路线
  • 400多位云计算专家和开发者,加入了同一个组织 ...
  • ​LeetCode解法汇总307. 区域和检索 - 数组可修改
  • ​力扣解法汇总1802. 有界数组中指定下标处的最大值
  • # dbt source dbt source freshness命令详解
  • #pragam once 和 #ifndef 预编译头
  • #我与Java虚拟机的故事#连载03:面试过的百度,滴滴,快手都问了这些问题
  • #我与Java虚拟机的故事#连载12:一本书带我深入Java领域
  • (1)(1.13) SiK无线电高级配置(六)
  • (1)(1.9) MSP (version 4.2)
  • (bean配置类的注解开发)学习Spring的第十三天
  • (Note)C++中的继承方式
  • (Windows环境)FFMPEG编译,包含编译x264以及x265
  • (八)c52学习之旅-中断实验
  • (博弈 sg入门)kiki's game -- hdu -- 2147
  • (附源码)ssm学生管理系统 毕业设计 141543
  • (黑马出品_高级篇_01)SpringCloud+RabbitMQ+Docker+Redis+搜索+分布式
  • (原創) 如何讓IE7按第二次Ctrl + Tab時,回到原來的索引標籤? (Web) (IE) (OS) (Windows)...
  • (转)拼包函数及网络封包的异常处理(含代码)
  • .NET 命令行参数包含应用程序路径吗?
  • .NET 中让 Task 支持带超时的异步等待
  • .NET/ASP.NETMVC 大型站点架构设计—迁移Model元数据设置项(自定义元数据提供程序)...
  • .NET导入Excel数据
  • .one4-V-XXXXXXXX勒索病毒数据怎么处理|数据解密恢复
  • /usr/bin/perl:bad interpreter:No such file or directory 的解决办法
  • /usr/local/nginx/logs/nginx.pid failed (2: No such file or directory)
  • [30期] 我的学习方法
  • [Android Pro] Notification的使用