Smalltalk 语言 命令模式实战 文本编辑器的撤销 / 重做

Smalltalk阿木 发布于 2025-05-29 9 次阅读


Smalltalk【1】 语言命令模式【2】实战:文本编辑器的撤销/重做功能实现

命令模式是一种行为设计模式,它将请求封装【3】为一个对象,从而允许用户对请求进行参数化、排队或记录请求,并支持可撤销的操作。在文本编辑器中,撤销和重做功能是用户最常用的功能之一。本文将使用Smalltalk语言,结合命令模式,实现一个简单的文本编辑器的撤销/重做功能。

Smalltalk 语言简介

Smalltalk是一种面向对象【4】编程语言,由Alan Kay等人于1970年代初期设计。它以其简洁的语法、强大的对象模型和动态类型【5】系统而闻名。Smalltalk语言的特点包括:

- 面向对象:所有代码都是对象,每个对象都有自己的属性和方法。
- 动态类型:变量的类型在运行时确定。
- 封装:对象的属性和方法被封装在一起,外部无法直接访问。
- 继承【6】:通过继承,子类可以继承父类的属性和方法。

命令模式概述

命令模式是一种设计模式,它将请求封装为一个对象,从而允许用户对请求进行参数化、排队或记录请求,并支持可撤销的操作。命令模式的主要组成部分包括:

- 命令(Command):定义执行操作的接口。
- 实现命令(ConcreteCommand):实现具体操作。
- 调用者【7】(Invoker):负责调用命令对象执行操作。
- 客户端【8】(Client):创建命令对象,并设置命令对象的接收者。

文本编辑器撤销/重做功能设计

1. 定义命令接口【9】

我们需要定义一个命令接口,它将包含执行操作和撤销操作的方法。

smalltalk
Command := Interface [
execute
undo
]

2. 实现具体命令【10】

接下来,我们实现具体的命令,例如`EditCommand`和`UndoCommand`。

smalltalk
EditCommand := Class [
| textEditor |
inheritFrom: Command.

initialize: textEditor [
self textEditor: textEditor
].

execute: text [
textEditor insert: text at: textEditor caretPosition
].

undo: [
textEditor remove: textEditor text at: textEditor caretPosition
].
]

3. 实现调用者

调用者负责创建命令对象,并设置命令对象的接收者。

smalltalk
TextEditor := Class [
| text |
inheritFrom: Object.

initialize: text [
self text: text
].

insert: text at: position [
self text: text, insert: text at: position
].

remove: text at: position [
self text: text, remove: text at: position
].

caretPosition: [ ... ] // 返回当前光标位置
]

4. 实现客户端

客户端负责创建命令对象,并调用命令对象的`execute`和`undo`方法。

smalltalk
editor := TextEditor new: 'Hello World'.
command := EditCommand new: editor.
command execute: ' Smalltalk'.
editor text // 输出: 'Hello World Smalltalk'
command undo.
editor text // 输出: 'Hello World'

撤销/重做功能实现

为了实现撤销/重做功能,我们需要维护一个命令栈【11】,用于存储执行过的命令和撤销过的命令。

smalltalk
CommandStack := Class [
| stack |
inheritFrom: Object.

initialize: [
self stack: List new
].

execute: command [
stack addLast: command.
command execute
].

undo: [
| lastCommand |
lastCommand := stack last.
lastCommand undo.
stack removeLast
].

redo: [
| lastCommand |
lastCommand := stack first.
lastCommand execute.
stack addLast: lastCommand.
stack removeFirst
].
]

现在,我们可以使用`CommandStack`来管理命令,实现撤销和重做功能。

smalltalk
stack := CommandStack new.
command := EditCommand new: editor.
stack execute: command.
stack undo.
stack redo.

总结

本文使用Smalltalk语言和命令模式实现了文本编辑器的撤销/重做功能。通过定义命令接口、实现具体命令、调用者和客户端,我们成功地封装了操作,并支持了撤销和重做功能。这种设计模式使得代码更加模块化【12】、可重用,并且易于维护。

在实际应用中,我们可以根据需要扩展命令模式,例如添加更多类型的命令、支持宏录制【13】等功能。通过命令模式,我们可以将操作与操作的具体实现解耦,从而提高代码的灵活性和可扩展性。