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

设计模式 18 备忘录模式

设计模式 18

  • 创建型模式(5):工厂方法模式、抽象工厂模式、单例模式、建造者模式、原型模式
  • 结构型模式(7):适配器模式、桥接模式、组合模式、装饰者模式、外观模式、享元模式、代理模式
  • 行为型模式(11):责任链模式、命令模式、解释器模式、迭代器模式、中介者模式、备忘录模式、观察者模式、状态模式、策略模式、模板方法模式、访问者模式

文章目录

  • 设计模式 18
    • 备忘录模式(Memento Pattern)
      • 1 定义
      • 2 结构
      • 3 示例代码
      • 6 特点
      • 7 适用场景
      • 8 总结

备忘录模式(Memento Pattern)

1 定义

备忘录模式的核心思想是将对象的状态保存在一个备忘录对象中,并允许在未来的某个时刻恢复该状态。备忘录模式保证了状态的封装性,外部对象无法直接访问备忘录中的内容,从而保护了原发器对象的内部细节。

2 结构

备忘录模式包含以下角色:

  • 原发器(Originator): 创建备忘录以记录当前状态,并可以使用备忘录恢复先前状态。
  • 备忘录(Memento): 存储原发器的内部状态,备忘录对外部是不可见的,只能由原发器访问。
  • 负责人(Caretaker): 负责存储和管理备忘录,但不会修改或检查备忘录的内容。

UML 类图

+---------------------------------------+      
|  Originator                           |       
+---------------------------------------+     
| - state: String                       |   
| + CreateMemento(): Memento            |  
| + SetMemento(memento: Memento): void  |  
+---------------------------------------+     |                          |                          
+-----------------------+           +-----------------------+
|   Memento             |           |   Caretaker           |
+-----------------------+           +-----------------------+
| - state: String       |           | - memento: Memento    |
| + GetState(): String  |           +-----------------------+
+-----------------------+     

3 示例代码

假设我们要实现一个简单的文本编辑器,它能够保存文本的状态,并在需要时撤销或恢复状态。

原发器

// 原发器类
public class TextEditor
{private string _text;public void SetText(string text){_text = text;}public string GetText(){return _text;}public Memento CreateMemento(){return new Memento(_text);}public void RestoreMemento(Memento memento){_text = memento.GetState();}
}

备忘录

// 备忘录类
public class Memento
{private readonly string _state;public Memento(string state){_state = state;}public string GetState(){return _state;}
}

负责人

// 负责人类
public class Caretaker
{private readonly Stack<Memento> _mementos = new Stack<Memento>();public void SaveMemento(Memento memento){_mementos.Push(memento);}public Memento GetMemento(){if (_mementos.Count > 0){return _mementos.Pop();}return null;}
}

客户端代码

class Program
{static void Main(string[] args){TextEditor editor = new TextEditor();Caretaker caretaker = new Caretaker();editor.SetText("Version 1");caretaker.SaveMemento(editor.CreateMemento());editor.SetText("Version 2");caretaker.SaveMemento(editor.CreateMemento());editor.SetText("Version 3");Console.WriteLine("Current Text: " + editor.GetText());editor.RestoreMemento(caretaker.GetMemento());Console.WriteLine("Restored Text: " + editor.GetText());editor.RestoreMemento(caretaker.GetMemento());Console.WriteLine("Restored Text: " + editor.GetText());}
}

运行结果

Current Text: Version 3
Restored Text: Version 2
Restored Text: Version 1

在这个例子中,TextEditor 是原发器,负责创建和恢复文本的状态;Memento 是备忘录,保存文本的状态;Caretaker 是负责人,管理备忘录的存储和恢复。在运行过程中,我们保存了多个文本状态,并通过恢复操作撤销了修改,返回到之前的状态。

6 特点

  • 优点:

    • 封装性: 备忘录模式保证了原发器状态的封装性,外部对象无法直接访问备忘录的内容。

    • 状态恢复: 允许对象恢复到之前的状态,提供了实现“撤销/恢复”功能的简单方法。

    • 简化复杂性: 通过将状态的存储和恢复职责分离到不同的类中,简化了复杂系统的管理。

  • 缺点:

    • 开销大: 如果原发器的状态占用大量资源(如内存),备忘录模式可能会导致开销较大,尤其是在频繁保存和恢复状态时。

    • 管理复杂: 如果备忘录数量众多,管理这些备忘录可能变得复杂,尤其是在涉及多线程操作时。

7 适用场景

  • 实现撤销/恢复功能: 当需要实现“撤销/恢复”操作时,备忘录模式非常适用。
  • 需要记录历史状态: 在需要保存和恢复对象的多个历史状态的场景中,可以使用备忘录模式。
  • 简化复杂对象的状态管理: 在复杂对象状态变化频繁且需要保证状态一致性的情况下,备忘录模式提供了一种有效的管理方式。

8 总结

备忘录模式通过保存对象的状态,提供了恢复该状态的机制。它通过封装状态,确保了对象内部细节的保护,同时又允许状态的恢复。该模式非常适合用于实现“撤销/恢复”功能,并在需要管理复杂状态变更的场景中提供了很好的解决方案。

相关文章:

  • 北京网站建设多少钱?
  • 辽宁网页制作哪家好_网站建设
  • 高端品牌网站建设_汉中网站制作
  • win11,vscode上用docker环境跑项目
  • graalvm jenkins maven 配置
  • 探索Ansible自动化运维:提高效率的关键工具
  • 【C++】手动实现String类的封装(分文件编译)
  • 程序员秋招经典面试题:简单聊聊DNS?
  • 什么是AOP(面向切面编程)
  • 一 lua学习笔记:概述
  • springboot酒店管理系统
  • C++类和对象2
  • 【单片机原理及应用】实验:数字秒表显示器
  • 24年7月-8月工作笔记整理(前端)
  • 惠中科技光伏清洗剂:科技创新引领绿色清洁新风尚
  • <数据集>车辆识别数据集<目标检测>
  • 详细阐述Android开发中常见的报错类型
  • .NetCore发布到IIS
  • [数据结构]链表的实现在PHP中
  • Apache的80端口被占用以及访问时报错403
  • canvas实际项目操作,包含:线条,圆形,扇形,图片绘制,图片圆角遮罩,矩形,弧形文字...
  • js作用域和this的理解
  • maya建模与骨骼动画快速实现人工鱼
  • node入门
  • PHP面试之三:MySQL数据库
  • yii2中session跨域名的问题
  • 从0到1:PostCSS 插件开发最佳实践
  • 在GitHub多个账号上使用不同的SSH的配置方法
  • 追踪解析 FutureTask 源码
  • HanLP分词命名实体提取详解
  • ​LeetCode解法汇总2583. 二叉树中的第 K 大层和
  • ​什么是bug?bug的源头在哪里?
  • #QT项目实战(天气预报)
  • #我与Java虚拟机的故事#连载16:打开Java世界大门的钥匙
  • (1)(1.8) MSP(MultiWii 串行协议)(4.1 版)
  • (70min)字节暑假实习二面(已挂)
  • (C语言)球球大作战
  • (附源码)ssm高校志愿者服务系统 毕业设计 011648
  • (南京观海微电子)——示波器使用介绍
  • (算法)Travel Information Center
  • .NET 5种线程安全集合
  • .NET CF命令行调试器MDbg入门(四) Attaching to Processes
  • .net core 6 使用注解自动注入实例,无需构造注入 autowrite4net
  • .Net Core和.Net Standard直观理解
  • .NET Core实战项目之CMS 第十二章 开发篇-Dapper封装CURD及仓储代码生成器实现
  • .NET 简介:跨平台、开源、高性能的开发平台
  • .NET 中使用 Mutex 进行跨越进程边界的同步
  • .NET 中小心嵌套等待的 Task,它可能会耗尽你线程池的现有资源,出现类似死锁的情况
  • .NET/C# 避免调试器不小心提前计算本应延迟计算的值
  • [20190401]关于semtimedop函数调用.txt
  • [Android 13]Input系列--获取触摸窗口
  • [Android]使用Android打包Unity工程
  • [BT]BUUCTF刷题第8天(3.26)
  • [BZOJ 4034][HAOI2015]T2 [树链剖分]
  • [Bzoj4722]由乃(线段树好题)(倍增处理模数小快速幂)
  • [C#]winform使用引导APSF和梯度自适应卷积增强夜间雾图像的可见性算法实现夜间雾霾图像的可见度增强
  • [C#]猫叫人醒老鼠跑 C#的委托及事件
  • [C/C++]数据结构 深入挖掘环形链表问题