设计模式Python版 备忘录模式

文章目录

  • 前言
  • 一、备忘录模式
  • 二、备忘录模式示例1
  • 三、备忘录模式示例2


前言

GOF设计模式分三大类:

  • 创建型模式:关注对象的创建过程,包括单例模式、简单工厂模式、工厂方法模式、抽象工厂模式、原型模式和建造者模式。
  • 结构型模式:关注类和对象之间的组合,包括适配器模式、桥接模式、组合模式、装饰模式、外观模式、享元模式和代理模式。
  • 行为型模式:关注对象之间的交互,包括职责链模式、命令模式、解释器模式、迭代器模式、中介者模式、备忘录模式、观察者模式、状态模式、策略模式、模板方法模式和访问者模式。

一、备忘录模式

备忘录模式(Memento Pattern)

  • 定义:在不破坏封装的前提下,捕获一个对象的内部状态,并在该对象之外保存这个状态,这样可以在以后将对象恢复到原先保存的状态。

  • 解决问题:如何在软件中实现撤销功能?

  • 使用场景:

    • 保存一个对象在某一个时刻的全部状态或部分状态,这样以后需要时就能够恢复到先前的状态,实现撤销操作。
    • 防止外界对象破坏一个对象历史状态的封装性,避免将对象历史状态的实现细节暴露给外界对象。
  • 组成:

    • Originator(原发器):它是一个普通类,可以创建一个备忘录,并存储其当前内部状态,也可以使用备忘录来恢复其内部状态。一般将需要保存内部状态的类设计为原发器。
    • Memento(备忘录):存储原发器的内部状态,根据原发器来决定保存哪些内部状态。备忘录的设计一般可以参考原发器的设计,根据实际需要确定备忘录类中的属性。需要注意的是,除了原发器本身与负责人类之外,备忘录对象不能直接供其他类使用。
    • Caretaker(负责人):负责人又称为管理者,他负责保存备忘录,但是不能对备忘录的内容进行操作或检查。在负责人类中可以存储一个或多个备忘录对象,他只负责存储对象,而不能修改对象,也无须知道对象的实现细节。
  • 补充说明:

    • 撤销功能的实现原理:在实现撤销时,首先必须保存软件系统的历史状态。当用户需要取消错误操作并且返回到某个历史状态时,可以取出事先保存的历史状态来覆盖当前状态。
    • 通过使用备忘录模式可以使系统恢复到某一特定的历史状态。当前很多软件都提供了撤销(Undo)操作,其中就使用了备忘录模式。
    • 备忘录模式的核心是备忘录类以及用于管理备忘录的负责人类的设计。
      • 在真实业务中,原发器类是一个具体的业务类,它包含一些用于存储成员数据的属性。
      • 对于备忘录类Memento而言,它通常提供了与原发器相对应的属性(可以是全部,也可以是部分)用于存储原发器的状态。
      • 对于负责人类Caretaker,它用于保存备忘录对象,并提供getMemento()方法用于向客户端返回一个备忘录对象。
  • 优点:

    • 它提供了一种状态恢复的实现机制,使得用户可以方便地回到一个特定的历史步骤。
    • 备忘录实现了对信息的封装。
  • 缺点:

    • 资源消耗过大

在这里插入图片描述

二、备忘录模式示例1

使用备忘录模式来设计中国象棋软件,提供“悔棋”功能

  • Chessman充当原发器,ChessmanMemento充当备忘录,MementoCaretaker充当负责人
  • 在MementoCaretaker中定义了一个ChessmanMemento类型的对象,用于存储备忘录。
### 备忘录模式
"""原发器:象棋棋子"""


class Chessman:
    def __init__(self, label: str, x: int, y: int):
        self.label = label
        self.x = x
        self.y = y

    def save(self) -> "ChessmanMemento":
        # 保存状态
        return ChessmanMemento(self.label, self.x, self.y)

    def restore(self, memento: "ChessmanMemento"):
        # 恢复状态
        self.label = memento.label
        self.x = memento.x
        self.y = memento.y


"""备忘录:象棋棋子备忘录"""


class ChessmanMemento:
    def __init__(self, label: str, x: int, y: int):
        self.label = label
        self.x = x
        self.y = y


"""负责人:象棋棋子备忘录管理"""


class MementoCaretaker:
    def __init__(self):
        self.memento: ChessmanMemento = None

    def get_memento(self):
        return self.memento

    def set_memento(self, memento: ChessmanMemento):
        self.memento = memento
  • 客户端代码
def display(chess: Chessman):
    print(f"棋子 {chess.label} 当前位置为:行 {chess.x}{chess.y}")


if __name__ == "__main__":
    mc = MementoCaretaker()
    chess = Chessman("车", 2, 2)
    display(chess)
    mc.set_memento(chess.save())  # 保存状态

    chess.y = 4
    display(chess)
    mc.set_memento(chess.save())  # 保存状态

    chess.x = 5
    display(chess)
    print("###悔棋###")
    chess.restore(mc.get_memento())  # 恢复状态
    display(chess)
  • 输出结果
棋子 车 当前位置为:行 22
棋子 车 当前位置为:行 24
棋子 车 当前位置为:行 54
###悔棋###
棋子 车 当前位置为:行 24

三、备忘录模式示例2

实现多次撤销

  • 在负责人类中定义列表来存储多个备忘录。修改负责人代码:
"""负责人:象棋棋子备忘录管理"""
class MementoCaretaker:
    def __init__(self):
        self.memento_list_f: list[ChessmanMemento] = []  # 前进状态
        self.memento_list_b: list[ChessmanMemento] = []  # 悔棋状态

    def get_memento_f(self):
        # 用于悔棋
        self.memento_list_b.append(self.memento_list_f.pop())
        return self.memento_list_f[-1]

    def get_memento_b(self):
        # 用于撤销悔棋
        memento = self.memento_list_b.pop()
        self.memento_list_f.append(memento)
        return memento

    def set_memento(self, memento: ChessmanMemento):
        # 下棋保存状态
        self.memento_list_b.clear()  # 棋子前进,则清空悔棋状态
        self.memento_list_f.append(memento)
  • 客户端代码
def display(chess: Chessman):
    print(f"棋子 {chess.label} 当前位置为:行 {chess.x}{chess.y}")


def play(chess: Chessman, mc: MementoCaretaker):
    # 下棋
    mc.set_memento(chess.save())  # 保存备忘录
    display(chess)


def undo(chess: Chessman, mc: MementoCaretaker):
    # 悔棋
    print("###悔棋###")
    chess.restore(mc.get_memento_f())
    display(chess)


def redo(chess: Chessman, mc: MementoCaretaker):
    # 撤销悔棋
    print("###撤销悔棋###")
    chess.restore(mc.get_memento_b())
    display(chess)


if __name__ == "__main__":
    mc = MementoCaretaker()
    chess = Chessman("车", 1, 1)
    play(chess, mc)
    chess.y = 4
    play(chess, mc)
    chess.x = 5
    play(chess, mc)
    undo(chess, mc)
    undo(chess, mc)
    redo(chess, mc)
    redo(chess, mc)
  • 输出结果
棋子 车 当前位置为:行 11
棋子 车 当前位置为:行 14
棋子 车 当前位置为:行 54
###悔棋###
棋子 车 当前位置为:行 14
###悔棋###
棋子 车 当前位置为:行 11
###撤销悔棋###
棋子 车 当前位置为:行 14
###撤销悔棋###
棋子 车 当前位置为:行 54

您正在阅读的是《设计模式Python版》专栏!关注不迷路~

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/978309.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Linux红帽:RHCSA认证知识讲解(三)Linux基础指令与Vim编辑器的使用

Linux红帽:RHCSA认证知识讲解(三)Linux基础指令与Vim编辑器的使用 前言一、Linux基础指令二、Linux 文件系统层次结构概念三、通过路径指定文件四、使用命令行工具管理文件五、Vim 的安装方式六、Vim 的操作模式七、红帽建议掌握的 Vim 键和命…

auto.js例子之WebView多页面浏览器

"ui";ui.layout(<vertical><horizontal id"webs" layout_weight"1"></horizontal><button id"one" text"第一个" /><button id"two" text"第二个" /><button id"…

跨平台公式兼容性大模型提示词模板(飞书 + CSDN + Microsoft Word)

飞书云文档 CSDN MD编辑器 Microsoft Word 跨平台公式兼容方案&#xff1a; 一、背景痛点与解决方案 在技术文档创作中&#xff0c;数学公式的跨平台渲染一直存在三大痛点&#xff1a; 飞书云文档&#xff1a;原生KaTeX渲染与导出功能存在语法限制微软Word&#xff1a;Math…

HTTP 动态报错码的原因和解决方法

目录 1xx&#xff08;信息性状态码&#xff09; 2xx&#xff08;成功状态码&#xff09; 3xx&#xff08;重定向状态码&#xff09; 4xx&#xff08;客户端错误状态码&#xff09; 5xx&#xff08;服务器错误状态码&#xff09; 参考文章 以下是 HTTP 动态报错码的常见原…

Docker基础-常见命令

docker images -查看所有的本地镜像。 docker pull -把远端镜像拉取到本地。 docker rmi -删除镜像。 docker push -推到镜像仓库。 docker run -创建并运行容器&#xff08;自动化&#xff0c;如果发现镜像不存在会先去拉取&#xff0c; 拉取完了以后再去自动创建容器&am…

Spring MVC框架六:Ajax技术

精心整理了最新的面试资料&#xff0c;有需要的可以自行获取 点击前往百度网盘获取 点击前往夸克网盘获取 简介 jQuery.ajax Ajax原理 结语 创作不易&#xff0c;希望能对大家给予帮助 想要获取更多资源? 点击链接获取

36. Spring Boot 2.1.3.RELEASE 中实现监控信息可视化并添加邮件报警功能

1. 创建 Spring Boot Admin Server 项目 1.1 添加依赖 在 pom.xml 中添加 Spring Boot Admin Server 和邮件相关依赖&#xff1a; <dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-w…

PowerShell 执行策略:fnm管理软件安装nodejs无法运行npm,错误信息:about_Execution_Policies

通过fnm管理软件安装NodeJS后添加环境变量依然无法执行npm,提示无法加载文件&#xff0c;错误如下&#xff1a; PowerShell 执行策略简介&#xff1a; PowerShell 执行策略是一项安全功能&#xff0c;用于控制 PowerShell 加载配置文件和运行脚本的条件。 此功能有助于防止恶…

Java在云计算平台中的应用研究

Java在云计算平台中的应用研究 随着云计算的广泛应用&#xff0c;越来越多的企业和开发者开始选择基于云计算的架构来构建和部署应用。Java作为一种成熟的编程语言&#xff0c;凭借其跨平台性、强大的生态系统以及优秀的并发处理能力&#xff0c;已成为云计算平台中常用的编程…

电脑键盘知识

1、键盘四大功能区 1. 功能区 2. 主要信息输入区 3. 编辑区 4. 数字键盘区 笔记本电脑键盘的功能区&#xff0c;使用前需先按Fn键 1.1、功能区 ESC&#xff1a;退出 F1&#xff1a;显示帮助信息 F2&#xff1a;重命名 F4&#xff1a;重复上一步操作 F5&#xff1a;刷新网页 …

论文阅读笔记:Continual Forgetting for Pre-trained Vision Models

论文阅读笔记&#xff1a;Continual Forgetting for Pre-trained Vision Models 1 背景2 创新点3 方法4 模块4.1 问题设置4.2 LoRA4.3 概述4.4 GS-LoRA4.5 损失函数 5 效果6 结论 1 背景 出于隐私和安全考虑&#xff0c;如今从预先训练的视觉模型中删除不需要的信息的需求越来…

C# 从基础神经元到实现在0~9数字识别

训练图片:mnist160 测试结果:1000次训练学习率为0.1时,准确率在60%以上 学习的图片越多&#xff0c;训练的时候越长(比如把 epochs*10 10000或更高时)效果越好 using System; using System.Collections.Generic; using System.Drawing; using System.IO; using System.Windo…

蓝桥杯 5.字符串

蓝桥杯 5.字符串 文章目录 蓝桥杯 5.字符串KMP&字符串哈希Manacher编程138-148字典树基础01Trie编程149-155 KMP&字符串哈希 KMP算法 字符串匹配算法, 用于匹配**模式串P(短)和文本串S(长)**中出现的所有位置, 例如, S “ababac”, P “aba”, 那么出现的所有位置就…

AI智能体与大语言模型:重塑SaaS系统的未来航向

在数字化转型的浪潮中&#xff0c;软件即服务&#xff08;SaaS&#xff09;系统一直是企业提升效率、优化业务流程的重要工具。随着AI智能体和大语言模型&#xff08;LLMs&#xff09;的迅速发展&#xff0c;SaaS系统正迎来前所未有的变革契机。本文将从AI智能体和大语言模型对…

Jmeter聚合报告导出log文档,Jmeter聚合报告导出到CSV

Jmeter聚合报告导出log文档 在Filename中输入 EKS_perf_log\\${type}_log\\${__P(UNIQUEID,${__time(YMDHMS)})}\all-graph-results-log.csv 可以得到执行的log&#xff0c;文件夹包含时间戳 Jmeter聚合报告导出到CSV 点击Save Table Data&#xff0c;保存到CSV文件中

基于SpringBoot的“古城景区管理系统”的设计与实现(源码+数据库+文档+PPT)

基于SpringBoot的“古城景区管理系统”的设计与实现&#xff08;源码数据库文档PPT) 开发语言&#xff1a;Java 数据库&#xff1a;MySQL 技术&#xff1a;SpringBoot 工具&#xff1a;IDEA/Ecilpse、Navicat、Maven 系统展示 系统整体功能图 系统首页界面 系统注册界面 景…

第五项修炼:打造学习型组织

“没有哪个教室比得上一个充满问题的团队。” — 彼得圣吉 最近有伙伴问我们&#xff0c;如何在组织中践行《第五项修炼&#xff1a;打造学习型组织》&#xff1f;我想和大家分享的是&#xff0c;这不仅仅是“学习”&#xff0c;更是通过结构和行为的深度结合&#xff0c;推动绩…

ubuntu22.04的docker容器中安装ssh服务

ubuntu22.04的docker容器中安装ssh服务&#xff0c;以便外部可以连接到容器中操作。 rootnode15:~# cat /etc/issue Ubuntu 22.04.5 LTS \n \l rootnode15:~# docker ps|grep qwen 7d3c36c37d36 vllm/vllm-openai:v0.7.3 "python3 -m …

LabVIEW 中 codeGenEngine.llb 工具库

codeGenEngine.llb 是 LabVIEW 2019 安装目录下C:\Program Files (x86)\National Instruments\LabVIEW 2019\vi.lib\Platform\路径下的工具库&#xff0c;主要用于代码生成相关的操作&#xff0c;帮助开发者在 LabVIEW 项目中便捷地实现自动化代码生成任务&#xff0c;提高开发…

基于LangChain4j调用火山引擎DeepSeek R1搭建RAG知识库实战指南

基于LangChain4j调用火山引擎DeepSeek R1搭建RAG知识库实战指南 基于LangChain4j调用火山引擎DeepSeek R1搭建RAG知识库实战指南 基于LangChain4j调用火山引擎DeepSeek R1搭建RAG知识库实战指南一、注册火山引擎账号二、RAG技术核心原理三、环境与工具准备1. 核心组件2. 依赖配…