备忘录模式:把你过去的状态都存储下来,让你可以随时回到过去
简介
备忘录模式(Memento Pattern)是一种行为型设计模式,它允许在不破坏对象封装性的情况下,捕获和保存对象的内部状态,并在需要时将对象恢复到先前的状态。该模式提供了一种保存对象状态的机制,使得对象可以在后续需要时恢复到之前的状态。
使用场景
备忘录模式适用于以下情况:
- 需要记录和恢复对象的状态,而不暴露其内部实现细节。
- 需要提供撤销功能,允许用户回退到先前的对象状态。
- 需要保存对象的某个特定时间点的状态,并在需要时进行恢复。
结构和角色
备忘录模式包含以下角色:
- 发起人(Originator):负责创建备忘录对象,并可以使用备忘录对象恢复其状态。
- 备忘录(Memento):用于存储发起人对象的内部状态。
- 负责人(Caretaker):负责保存备忘录对象,并在需要时将其提供给发起人。
示例:在Vue3中使用
假设您正在开发一个Vue3应用程序,该应用程序具有角色管理功能。您希望提供一个撤销功能,允许用户回退到之前的角色状态。我们将使用备忘录模式来实现这一功能。
1. 定义发起人(Originator)
在我们的示例中,发起人是角色管理器(RoleManager),它负责管理角色的状态。发起人的代码如下:
import { reactive, toRefs } from 'vue';
// 创建角色管理器
export function createRoleManager() {
// 角色状态
const state = reactive({
roles: [],
});
// 添加角色
function addRole(role) {
state.roles.push(role);
}
// 保存角色状态的备忘录
function saveState() {
const snapshot = JSON.stringify(state.roles);
return { snapshot };
}
// 恢复角色状态
function restoreState(memento) {
state.roles = JSON.parse(memento.snapshot);
}
// 导出响应式状态
return {
...toRefs(state),
addRole,
saveState,
restoreState,
};
}
发起人(RoleManager)使用Vue3的响应式函数(reactive)来创建一个包含角色状态的响应式对象。它包含以下功能:
addRole(role)
: 添加角色到角色管理器中。saveState()
: 创建并返回当前角色状态的备忘录对象。restoreState(memento)
: 使用备忘录对象恢复角色状态。
2. 定义备忘录(Memento)
备忘录(Memento)对象用于存储角色管理器(RoleManager)的状态快照。在我们的示例中,备忘录对象将保存角色数组的快照。
// 创建备忘录对象
export function createMemento(snapshot) {
return {
snapshot,
};
}
备忘录对象(Memento)是一个简单的函数,它接收一个快照参数,并返回一个包含快照的备忘录对象。
3. 使用备忘录模式
我们现在可以在Vue组件中使用备忘录模式来实现撤销功能。以下是一个简单的Vue组件示例:
<template>
<div>
<h2>角色管理</h2>
<ul>
<li v-for="role in roles" :key="role.id">{{ role.name }}</li>
</ul>
<button @click="addRole">添加角色</button>
<button @click="undo">撤销</button>
</div>
</template>
<script>
import { createRoleManager, createMemento } from './roleManager';
export default {
setup() {
const roleManager = createRoleManager();
// 添加角色
function addRole() {
const role = { id: Date.now(), name: '角色名称' };
roleManager.addRole(role);
}
// 撤销操作
function undo() {
const memento = roleManager.saveState();
roleManager.restoreState(memento);
}
return {
...roleManager,
addRole,
undo,
};
},
};
</script>
在上述示例中,我们创建了一个Vue组件来管理角色。通过调用addRole
方法,我们可以向角色管理器中添加一个新角色。通过调用undo
方法,我们可以撤销到之前的角色状态。
在undo
方法中,我们首先调用roleManager.saveState()
来保存当前角色状态的备忘录对象。然后,我们再次调用roleManager.restoreState(memento)
,将角色状态恢复到之前的状态。
通过在Vue组件中使用备忘录模式,我们实现了撤销功能,允许用户回退到之前的角色状态。
在原生 JavaScript 项目中使用备忘录模式的实现案例:
// 发起人(Originator)
class TextEditor {
constructor() {
this.content = '';
}
type(text) {
this.content += text;
}
getContent() {
return this.content;
}
createMemento() {
return new Memento(this.content);
}
restoreFromMemento(memento) {
this.content = memento.getContent();
}
}
// 备忘录(Memento)
class Memento {
constructor(content) {
this.content = content;
}
getContent() {
return this.content;
}
}
// 负责人(Caretaker)
class History {
constructor() {
this.mementos = [];
}
push(memento) {
this.mementos.push(memento);
}
pop() {
return this.mementos.pop();
}
}
// 使用备忘录模式保存和恢复文本编辑器的状态
const textEditor = new TextEditor();
const history = new History();
textEditor.type('Hello, ');
history.push(textEditor.createMemento());
textEditor.type('world!');
console.log(textEditor.getContent()); // Output: Hello, world!
textEditor.restoreFromMemento(history.pop());
console.log(textEditor.getContent()); // Output: Hello,
在这个案例中,我们创建了一个简单的文本编辑器(TextEditor),它具有输入文本、获取内容、创建备忘录和从备忘录恢复的功能。我们还创建了一个历史记录(History)来保存备忘录对象。
首先,我们向文本编辑器输入文本并创建一个备忘录,然后将其压入历史记录中。然后,我们继续输入更多的文本。最后,我们通过弹出历史记录中的备忘录对象,将文本编辑器恢复到之前的状态。
通过使用备忘录模式,我们可以在不破坏文本编辑器封装性的情况下,保存和恢复其状态。这对于实现撤销/重做功能或保存应用程序的某个特定时间点的状态非常有用。
下面是一个在React中使用备忘录模式的示例:
import React, { useState } from 'react';
// 备忘录对象(Memento)
class Memento {
constructor(content) {
this.content = content;
}
getContent() {
return this.content;
}
}
// 角色管理器(Originator)
const RoleManager = () => {
const [roles, setRoles] = useState([]);
const [memento, setMemento] = useState(null);
// 添加角色
const addRole = () => {
const newRole = { id: Date.now(), name: '新角色' };
setRoles((prevRoles) => [...prevRoles, newRole]);
};
// 保存状态到备忘录
const saveState = () => {
setMemento(new Memento(roles));
};
// 恢复状态
const restoreState = () => {
if (memento) {
setRoles(memento.getContent());
setMemento(null);
}
};
return (
<div>
<h2>角色管理</h2>
<ul>
{roles.map((role) => (
<li key={role.id}>{role.name}</li>
))}
</ul>
<button onClick={addRole}>添加角色</button>
<button onClick={saveState}>保存状态</button>
<button onClick={restoreState}>恢复状态</button>
</div>
);
};
export default RoleManager;
在这个案例中,我们使用React函数式组件和React Hooks来管理角色的状态和备忘录。RoleManager
组件中包含了一个角色列表roles
和一个备忘录memento
的状态。
通过点击"添加角色"按钮,我们可以向角色列表中添加新角色。通过点击"保存状态"按钮,我们可以将当前角色列表的状态保存到备忘录中。通过点击"恢复状态"按钮,我们可以将角色列表恢复到之前保存的状态。
这样,我们就实现了在React应用中使用备忘录模式来保存和恢复状态的功能。通过将状态保存到备忘录对象中,我们可以实现撤销操作或恢复到之前的状态。
结论
备忘录模式是一种非常有用的设计模式,可以在需要时保存和恢复对象的状态,实现撤销和重做功能。在本文中,我们演示了如何在Vue3的组件和setup函数中使用备忘录模式来实现撤销功能。通过将角色状态封装在备忘录对象中,我们能够保存和恢复角色管理器的状态,使用户能够回退到之前的状态。
备忘录模式的灵活性使其适用于各种场景,包括文本编辑器、游戏进度管理、撤销/重做功能等。通过将对象状态的保存和恢复功能委托给备忘录对象,我们可以更好地管理对象的状态变化,并提供更好的用户
转载自:https://juejin.cn/post/7238885536827277371