简介
备忘录模式(Memento Pattern)是一种结构型设计模式。这种模式就是在不破坏封装的条件下,将一个对象的状态捕捉(Capture)住,并放在外部存储起来,从而可以在将来合适的时候把这个对象还原到存储起来的状态。备忘录模式常常与命令模式和迭代子模式一同使用。
备忘录模式的角色有三个:备忘录(Memento)角色、发起人(Originator)角色、负责人(Caretaker)角色
备忘录模式是由发起人(Originator)对象负责生成状态快照,其他对象不可修改状态。再将对象状态的副本存储在一个名为备忘录(Memento)的特殊对象中。除了创建备忘录的对象外,任何对象都不能访问备忘录的内容。其他对象必须使用指定接口与备忘录进行交互,它们可以获取快照的元数据(创建时间和操作名称等),但不能获取快照中原始对象的状态。
这种限制策略允许你将备忘录保存在通常被称为负责人(Caretakers)的对象历史中。由于负责人仅通过受限接口与备忘录互动,故其无法修改存储在备忘录内部的状态。同时,发起人拥有对备忘录所有成员的访问权限,从而能随时恢复其以前的某个状态。
作用
- 给用户提供了一种可以恢复状态的机制,可以使用户能够比较方便地回到某个历史的状态。
- 实现了内部状态的封装,除了创建它的发起人之外,其他对象都不能够访问这些状态信息,也不需要关心状态的保存细节。
- 简化了发起人角色,发起人不需要管理和保存其内部状态的各个备份,所有状态信息都保存在备忘录中,并由负责人进行管理,符合单一职责原则。
实现步骤
- 创建备忘录Memento,用来记录操作状态数据的实体类。
- 创建发起人角色Originator,状态的制造者,也是备忘录的生成者,负责将状态写入到一个新备忘录。
- 创建负责人角色Caretaker,用来保存和读取备忘录的历史记录,所有备忘录均可以保存在历史中,以便恢复。
- 客户调用方通过Originator来生成备忘录,再通过Caretaker读取和恢复备忘录历史记录。
UML
Java代码
具体备忘录
| |
| public class Memento { |
| private String state; |
| |
| public Memento(String state) { |
| System.out.println(this.getClass().getName() + "::Memento() [state = " + state + "]"); |
| this.state = state; |
| } |
| |
| public String getState() { |
| return state; |
| } |
| |
| public void setState(String state) { |
| this.state = state; |
| } |
| } |
发起人
| |
| public class Originator { |
| |
| private String state; |
| |
| |
| public Memento saveMemento() { |
| System.out.println(this.getClass().getName() + "::saveMemento() [state = " + state + "]"); |
| return new Memento(state); |
| } |
| |
| |
| public void restoreMemento(Memento memento) { |
| this.state = memento.getState(); |
| } |
| |
| public String getState() { |
| return state; |
| } |
| |
| public void setState(String state) { |
| this.state = state; |
| } |
| } |
负责人类
| |
| public class Caretaker { |
| |
| private List<Memento> mementoList = new ArrayList<Memento>(); |
| |
| public void add(Memento memento) { |
| System.out.println(this.getClass().getName() + "::add() [memento = " + memento.getClass().getName() + "]"); |
| mementoList.add(memento); |
| } |
| |
| public Memento get(int index) { |
| return mementoList.get(index); |
| } |
| |
| public List<Memento> getMementoList() { |
| return this.mementoList; |
| } |
| } |
测试调用
| |
| |
| |
| |
| |
| Originator originator = new Originator(); |
| Caretaker careTaker = new Caretaker(); |
| |
| originator.setState("state1"); |
| |
| originator.setState("state2"); |
| |
| Memento memento = originator.saveMemento(); |
| |
| careTaker.add(memento); |
| |
| |
| originator.setState("state3"); |
| careTaker.add(originator.saveMemento()); |
| originator.setState("state4"); |
| careTaker.add(originator.saveMemento()); |
| |
| System.out.println("发起人当前的状态: " + originator.getState()); |
| |
| |
| originator.restoreMemento(careTaker.get(0)); |
| System.out.println("第一个保存的状态: " + originator.getState()); |
| originator.restoreMemento(careTaker.get(1)); |
| System.out.println("第二个保存的状态: " + originator.getState()); |
| |
| |
| for (int i = 0; i < careTaker.getMementoList().size(); i++) { |
| |
| originator.restoreMemento(careTaker.get(i)); |
| System.out.println("state: " + i + ")" + originator.getState()); |
| } |
JavaScript代码
具体备忘录
| |
| |
| export class Memento { |
| constructor(state) { |
| console.log(this.constructor.name + '::Memento() [state = ' + state + ']') |
| this.state = state |
| } |
| |
| getState() { |
| return this.state |
| } |
| |
| setState(state) { |
| this.state = state |
| } |
| } |
| |
发起人
| |
| import { Memento } from './Memento.js' |
| |
| export class Originator { |
| constructor() { |
| this.state = undefined |
| } |
| |
| |
| saveMemento() { |
| console.log( |
| this.constructor.name + '::saveMemento() [state = ' + this.state + ']' |
| ) |
| return new Memento(this.state) |
| } |
| |
| |
| restoreMemento(memento) { |
| this.state = memento.getState() |
| } |
| |
| getState() { |
| return this.state |
| } |
| |
| setState(state) { |
| this.state = state |
| } |
| } |
负责人类
| |
| export class Caretaker { |
| constructor() { |
| |
| this.mementoList = [] |
| } |
| |
| add(memento) { |
| console.log( |
| this.constructor.name + |
| '::add() [memento = ' + |
| memento.constructor.name + |
| ']' |
| ) |
| this.mementoList.push(memento) |
| } |
| |
| get(index) { |
| return this.mementoList[index] |
| } |
| |
| getMementoList() { |
| return this.mementoList |
| } |
| } |
测试调用
| import { Originator } from '../src/Originator.js' |
| import { Caretaker } from '../src/Caretaker.js' |
| |
| export function test() { |
| |
| |
| |
| |
| |
| const originator = new Originator() |
| const careTaker = new Caretaker() |
| |
| originator.setState('state1') |
| |
| originator.setState('state2') |
| |
| const memento = originator.saveMemento() |
| |
| careTaker.add(memento) |
| |
| |
| originator.setState('state3') |
| careTaker.add(originator.saveMemento()) |
| originator.setState('state4') |
| careTaker.add(originator.saveMemento()) |
| |
| console.log('发起人当前的状态: ' + originator.getState()) |
| |
| |
| originator.restoreMemento(careTaker.get(0)) |
| console.log('第一个保存的状态: ' + originator.getState()) |
| originator.restoreMemento(careTaker.get(1)) |
| console.log('第二个保存的状态: ' + originator.getState()) |
| |
| |
| for (let i = 0; i < careTaker.getMementoList().length; i++) { |
| |
| originator.restoreMemento(careTaker.get(i)) |
| console.log('state: ' + i + ')' + originator.getState()) |
| } |
| } |
| |
| |
| ;(function () { |
| console.log('test start:') |
| test() |
| })() |
更多语言版本
不同语言实现设计模式:https://github.com/microwind/design-pattern
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 【自荐】一款简洁、开源的在线白板工具 Drawnix
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY
· Docker 太简单,K8s 太复杂?w7panel 让容器管理更轻松!