TypeScript设计模式:备忘录模式

备忘录模式(Memento Pattern)是一种行为型设计模式,通过捕获对象的内部状态,并在不破坏封装的情况下保存这个状态,以便稍后恢复到先前的状态。这种模式常用于实现撤销/重做功能、状态快照和历史记录管理。

设计模式原理

备忘录模式的核心是通过备忘录对象封装发起人的内部状态,保管人负责存储和传递备忘录,而不直接访问状态,从而保护封装性。

结构

  • 发起人(Originator):创建备忘录,保存当前状态到备忘录中,并从备忘录恢复状态。
  • 备忘录(Memento):存储发起人的内部状态,提供狭窄接口给保管人,宽接口给发起人。
  • 保管人(Caretaker):负责保存备忘录,但不检查或修改其内容。

优点

  • 封装性强:保管人无法访问或修改备忘录内部状态,保护发起人隐私。
  • 简单实现:易于添加保存/恢复功能,无需暴露内部细节。
  • 支持历史管理:可维护状态栈,实现撤销/重做。
  • 灵活扩展:备忘录可序列化,支持持久化存储。

缺点

  • 内存消耗:大量备忘录可能占用过多内存。
  • 复杂状态:深层嵌套对象需深拷贝,避免引用问题。
  • 性能影响:频繁保存/恢复可能导致开销。
  • 版本兼容:状态变化时,旧备忘录可能失效。

适用场景

  • 撤销/重做:如文本编辑器、图形工具。
  • 状态快照:如游戏存档、AI对话历史。
  • 历史回放:如日志系统、调试工具。
  • 智能代理:如AI记忆管理,支持回滚决策。

TypeScript 实现示例

我们实现一个AI智能体记忆系统,智能体通过备忘录保存对话历史和状态,支持回滚和恢复。代码使用TypeScript确保类型安全。

项目结构

go 复制代码
ai-memory/
├── src/
│   ├── memento.ts       // 核心接口
│   ├── agent.ts        // 发起人
│   ├── memoryManager.ts // 保管人
│   ├── main.ts         // 执行示例
├── tsconfig.json
├── package.json

1. 安装依赖

bash 复制代码
npm init -y
npm install typescript @types/node
npx tsc --init

配置 tsconfig.json

json 复制代码
{
  "compilerOptions": {
    "target": "ES2020",
    "module": "ESNext",
    "strict": true,
    "moduleResolution": "node"
  }
}

2. 定义接口 (memento.ts)

typescript 复制代码
export interface Memento {
  getState(): any;
  setState(state: any): void;
}

export interface Originator {
  createMemento(): Memento;
  restore(memento: Memento): void;
  getState(): any;
  setState(state: any): void;
}

export interface Caretaker {
  saveMemento(memento: Memento): void;
  restoreMemento(): Memento | null;
  undo(): Memento | null;
}

3. 实现发起人 (agent.ts)

typescript 复制代码
import { Memento, Originator } from './memento';

interface AIMemoryState {
  conversation: string[];
  decisions: string[];
  timestamp: number;
}

export class AIAgent implements Originator {
  private state: AIMemoryState;

  constructor(initialState: AIMemoryState) {
    this.state = initialState;
  }

  createMemento(): Memento {
    return new MemoryMemento({ ...this.state });
  }

  restore(memento: Memento): void {
    this.state = memento.getState();
    console.log('AI代理状态已恢复');
  }

  getState(): AIMemoryState {
    return { ...this.state };
  }

  setState(newState: Partial<AIMemoryState>): void {
    this.state = { ...this.state, ...newState };
  }

  // AI行动:添加对话和决策
  addConversation(message: string): void {
    this.state.conversation.push(message);
    console.log(`对话添加:${message}`);
  }

  makeDecision(decision: string): void {
    this.state.decisions.push(decision);
    this.state.timestamp = Date.now();
    console.log(`决策添加:${decision}`);
  }
}

class MemoryMemento implements Memento {
  private state: AIMemoryState;

  constructor(state: AIMemoryState) {
    this.state = { ...state };
  }

  getState(): AIMemoryState {
    return { ...this.state };
  }

  setState(state: AIMemoryState): void {
    this.state = { ...state };
  }
}

4. 实现保管人 (memoryManager.ts)

typescript 复制代码
import { Memento, Caretaker } from './memento';

export class MemoryManager implements Caretaker {
  private mementos: Memento[] = [];

  saveMemento(memento: Memento): void {
    this.mementos.push(memento);
    console.log('备忘录已保存');
  }

  restoreMemento(): Memento | null {
    if (this.mementos.length === 0) {
      console.log('无备忘录可恢复');
      return null;
    }
    const memento = this.mementos.pop()!;
    console.log('备忘录已恢复');
    return memento;
  }

  undo(): Memento | null {
    if (this.mementos.length < 2) {
      console.log('无法回滚');
      return null;
    }
    const previous = this.mementos.pop()!;
    console.log('状态已回滚');
    return previous;
  }

  getHistorySize(): number {
    return this.mementos.length;
  }
}

5. 运行示例 (main.ts)

typescript 复制代码
import { AIAgent } from './agent';
import { MemoryManager } from './memoryManager';

const initialState = {
  conversation: ['系统启动'],
  decisions: [],
  timestamp: Date.now()
};

const agent = new AIAgent(initialState);
const manager = new MemoryManager();

// 初始保存
manager.saveMemento(agent.createMemento());

// 第一步行动
agent.addConversation('用户:你好');
agent.makeDecision('问候用户');
manager.saveMemento(agent.createMemento());

// 第二步行动
agent.addConversation('用户:今天天气如何?');
agent.makeDecision('查询天气');
manager.saveMemento(agent.createMemento());

// 模拟错误,回滚
console.log('当前状态:', agent.getState());
const previousMemento = manager.undo();
if (previousMemento) {
  agent.restore(previousMemento);
  console.log('回滚后状态:', agent.getState());
}

// 恢复最后状态
const lastMemento = manager.restoreMemento();
if (lastMemento) {
  agent.restore(lastMemento);
  console.log('恢复后状态:', agent.getState());
}

console.log(`历史记录大小:${manager.getHistorySize()}`);

6. 编译与运行

bash 复制代码
npx tsc
node dist/main.js

运行后,控制台输出类似:

css 复制代码
备忘录已保存
对话添加:用户:你好
决策添加:问候用户
备忘录已保存
对话添加:用户:今天天气如何?
决策添加:查询天气
备忘录已保存
当前状态: { conversation: [ '系统启动', '用户:你好', '用户:今天天气如何?' ], decisions: [ '问候用户', '查询天气' ], timestamp: 1695090000000 }
状态已回滚
AI代理状态已恢复
回滚后状态: { conversation: [ '系统启动', '用户:你好' ], decisions: [ '问候用户' ], timestamp: 1695090000000 }
备忘录已恢复
AI代理状态已恢复
恢复后状态: { conversation: [ '系统启动', '用户:你好', '用户:今天天气如何?' ], decisions: [ '问候用户', '查询天气' ], timestamp: 1695090000000 }
历史记录大小:1

总结

备忘录模式的优点在于其封装性强、简单实现、支持历史管理和灵活扩展。发起人状态通过备忘录封装,保管人无法直接访问,确保隐私保护;易于添加保存/恢复功能,无需暴露内部细节;可维护状态栈,实现撤销/重做;备忘录可序列化,支持持久化存储。该模式特别适用于撤销/重做、状态快照、历史回放和智能代理场景,如文本编辑器、游戏存档、日志系统,以及AI对话历史管理,支持回滚决策避免错误累积。

相关推荐
阿笑带你学前端2 小时前
Flutter本地通知系统:记账提醒的深度实现
前端·flutter
白衣鸽子2 小时前
PageHelper:分页陷阱避免与最佳实践
后端
BingoGo2 小时前
PHP 和 Elasticsearch:给你的应用加个强力搜索引擎
后端·php
泉城老铁2 小时前
Spring Boot对接抖音获取H5直播链接详细指南
spring boot·后端·架构
武子康2 小时前
大数据-101 Spark Streaming 有状态转换详解:窗口操作与状态跟踪实战 附多案例代码
大数据·后端·spark
数据小馒头2 小时前
企业级数据库管理实战(五):多数据库与异构环境的统一管理
后端
天天摸鱼的java工程师2 小时前
SpringBoot + RabbitMQ + MySQL + XXL-Job:物流系统运单状态定时同步与异常订单重试
后端
RoyLin2 小时前
TypeScript设计模式:仲裁者模式
前端·后端·typescript
粘豆煮包2 小时前
掀起你的盖头来之《数据库揭秘》-3-SQL 核心技能速成笔记-查询、过滤、排序、分组等
后端·mysql