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

基于typescript严格模式以实现undo和redo功能为目标的命令模式代码参考

下面是一个完整的、严格模式下的 TypeScript 实现,包含 CommandManager、Command 和 CompositeCommand 类,支持 undo/redo 功能。

完整实现代码

1. Command 接口和基类

// src/commands/ICommand.ts
export interface ICommand {execute(): void;undo(): void;redo(): void;
}
// src/commands/Command.ts
import { ICommand } from "./ICommand";export abstract class Command implements ICommand {private _isExecuted: boolean = false;public execute(): void {if (!this._isExecuted) {this.doExecute();this._isExecuted = true;}}public undo(): void {if (this._isExecuted) {this.doUndo();this._isExecuted = false;}}public redo(): void {if (!this._isExecuted) {this.doExecute();this._isExecuted = true;}}protected abstract doExecute(): void;protected abstract doUndo(): void;public get isExecuted(): boolean {return this._isExecuted;}
}

2. CompositeCommand 实现

// src/commands/CompositeCommand.ts
import { ICommand } from "./ICommand";
import { Command } from "./Command";export class CompositeCommand extends Command {private readonly _commands: ICommand[] = [];public addCommand(command: ICommand): void {this._commands.push(command);}public removeCommand(command: ICommand): void {const index = this._commands.indexOf(command);if (index !== -1) {this._commands.splice(index, 1);}}public clearCommands(): void {this._commands.length = 0;}public get commands(): ReadonlyArray<ICommand> {return this._commands;}protected doExecute(): void {for (const command of this._commands) {command.execute();}}protected doUndo(): void {// Undo in reverse orderfor (let i = this._commands.length - 1; i >= 0; i--) {this._commands[i].undo();}}
}

3. CommandManager 实现

// src/commands/CommandManager.ts
import { ICommand } from "./ICommand";export class CommandManager {private readonly _undoStack: ICommand[] = [];private readonly _redoStack: ICommand[] = [];private readonly _maxStackSize: number;constructor(maxStackSize: number = 100) {this._maxStackSize = maxStackSize;}public execute(command: ICommand): void {command.execute();this._undoStack.push(command);// Clear redo stack when executing a new commandthis._redoStack.length = 0;// Ensure we don't exceed max stack sizeif (this._undoStack.length > this._maxStackSize) {this._undoStack.shift();}}public undo(): boolean {const command = this._undoStack.pop();if (command) {command.undo();this._redoStack.push(command);return true;}return false;}public redo(): boolean {const command = this._redoStack.pop();if (command) {command.redo();this._undoStack.push(command);return true;}return false;}public clearHistory(): void {this._undoStack.length = 0;this._redoStack.length = 0;}public get canUndo(): boolean {return this._undoStack.length > 0;}public get canRedo(): boolean {return this._redoStack.length > 0;}public get undoStackSize(): number {return this._undoStack.length;}public get redoStackSize(): number {return this._redoStack.length;}
}

示例使用代码

// src/main.ts
import { CommandManager } from "./commands/CommandManager";
import { Command } from "./commands/Command";
import { CompositeCommand } from "./commands/CompositeCommand";// 示例命令 - 修改文本
class ChangeTextCommand extends Command {constructor(private _target: { text: string },private _newText: string,private _oldText: string) {super();}protected doExecute(): void {this._target.text = this._newText;console.log(`Text changed to: ${this._newText}`);}protected doUndo(): void {this._target.text = this._oldText;console.log(`Text reverted to: ${this._oldText}`);}
}// 示例命令 - 修改数字
class ChangeNumberCommand extends Command {constructor(private _target: { value: number },private _newValue: number,private _oldValue: number) {super();}protected doExecute(): void {this._target.value = this._newValue;console.log(`Number changed to: ${this._newValue}`);}protected doUndo(): void {this._target.value = this._oldValue;console.log(`Number reverted to: ${this._oldValue}`);}
}// 使用示例
const commandManager = new CommandManager();const textObject = { text: "Initial text" };
const numberObject = { value: 0 };// 创建并执行单个命令
const changeTextCommand = new ChangeTextCommand(textObject, "New text", textObject.text);
commandManager.execute(changeTextCommand);// 创建并执行组合命令
const compositeCommand = new CompositeCommand();
compositeCommand.addCommand(new ChangeTextCommand(textObject, "Composite text", textObject.text));
compositeCommand.addCommand(new ChangeNumberCommand(numberObject, 42, numberObject.value));
commandManager.execute(compositeCommand);// 测试 undo/redo
console.log("--- Undo ---");
commandManager.undo(); // 撤销组合命令
console.log("Current text:", textObject.text);
console.log("Current number:", numberObject.value);console.log("--- Redo ---");
commandManager.redo(); // 重做组合命令
console.log("Current text:", textObject.text);
console.log("Current number:", numberObject.value);console.log("--- Undo single command ---");
commandManager.undo(); // 撤销组合命令
commandManager.undo(); // 撤销第一个文本修改命令
console.log("Current text:", textObject.text);

严格模式配置

确保你的 tsconfig.json 包含严格模式设置:

{"compilerOptions": {"strict": true,"noImplicitAny": true,"strictNullChecks": true,"strictFunctionTypes": true,"strictBindCallApply": true,"strictPropertyInitialization": true,"noImplicitThis": true,"alwaysStrict": true}
}

设计说明

  1. ICommand 接口:定义了命令模式的基本操作

  2. Command 抽象类

    • 实现了基础执行状态跟踪

    • 要求子类实现实际执行和撤销逻辑

  3. CompositeCommand

    • 可以组合多个命令一起执行

    • 撤销时按相反顺序执行

  4. CommandManager

    • 管理 undo/redo 堆栈

    • 限制最大堆栈大小防止内存问题

    • 提供清晰的API和状态查询

这个实现是完全类型安全的,符合 TypeScript 严格模式要求,并且可以直接集成到 Vite 项目中。

http://www.dtcms.com/a/283876.html

相关文章:

  • Python-TCP编程-UDP编程-SocketServer-IO各种概念及多路复用-asyncio-学习笔记
  • 从0开始学习R语言--Day49--Lasso-Cox 回归
  • 在UniApp中防止页面上下拖动的方法
  • git@github.com: Permission denied (publickey).
  • 算法竞赛备赛——【图论】求最短路径——Dijkstra
  • 排序算法—交换排序(冒泡、快速)(动图演示)
  • uniapp问题总结
  • 并发事务~
  • 一种融合人工智能与图像处理的发票OCR技术,将人力从繁琐的票据处理中解放
  • 视频安全新思路:VRM视频分片错序加密技术
  • 小架构step系列17:getter-setter-toString
  • 智能视频分析:多行业安全防控的“AI之眼”
  • 嵌入式学习-PyTorch(7)-day23
  • Flutter Android打包学习指南
  • 如何下载视频 (pc端任何视频均可下载)
  • 英伟达Cosmos研究团队开源DiffusionRenderer (Cosmos): 神经逆向与正向渲染与视频扩散模型
  • 视频码率是什么?视频流分辨率 2688x1520_25fps采用 h264格式压缩,其码率为
  • Web攻防-PHP反序列化Phar文件类CLI框架类PHPGGC生成器TPYiiLaravel
  • blender 导入的fbx模型位置错乱
  • 【3D大比拼第一集】--max,maya,c4d,blender的命令搜索功能
  • iOS App 电池消耗管理与优化 提升用户体验的完整指南
  • 【力扣 中等 C】97. 交错字符串
  • 量化环节:Cont‘d
  • 题解:CF1829H Don‘t Blame Me
  • 相位中心偏置天线的SAR动目标检测
  • 代码随想录算法训练营第二十三天
  • Apache SeaTunnel配置使用案例
  • 【Leetcode】栈和队列算法题(逆波兰表达式、二叉树层序遍历、最小栈、栈的压入弹出序列)
  • 贪心算法(排序)
  • 如何通过ATS/HTTPS数据防篡改来加密视频?