命令模式
问题
Rust 中命令模式如何实现?典型应用场景是什么?
答案
命令模式将操作封装为对象,支持撤销/重做、队列化、日志记录。
实现:文本编辑器撤销/重做
trait Command {
fn execute(&mut self, doc: &mut String);
fn undo(&mut self, doc: &mut String);
}
struct InsertText {
position: usize,
text: String,
}
impl Command for InsertText {
fn execute(&mut self, doc: &mut String) {
doc.insert_str(self.position, &self.text);
}
fn undo(&mut self, doc: &mut String) {
let end = self.position + self.text.len();
doc.replace_range(self.position..end, "");
}
}
struct DeleteText {
position: usize,
length: usize,
deleted: String, // 保存被删除的文本用于 undo
}
impl Command for DeleteText {
fn execute(&mut self, doc: &mut String) {
self.deleted = doc[self.position..self.position + self.length].to_string();
doc.replace_range(self.position..self.position + self.length, "");
}
fn undo(&mut self, doc: &mut String) {
doc.insert_str(self.position, &self.deleted);
}
}
// 命令管理器
struct Editor {
document: String,
history: Vec<Box<dyn Command>>,
redo_stack: Vec<Box<dyn Command>>,
}
impl Editor {
fn execute(&mut self, mut cmd: Box<dyn Command>) {
cmd.execute(&mut self.document);
self.history.push(cmd);
self.redo_stack.clear();
}
fn undo(&mut self) {
if let Some(mut cmd) = self.history.pop() {
cmd.undo(&mut self.document);
self.redo_stack.push(cmd);
}
}
fn redo(&mut self) {
if let Some(mut cmd) = self.redo_stack.pop() {
cmd.execute(&mut self.document);
self.history.push(cmd);
}
}
}
常见面试问题
Q1: 命令模式在哪些场景下有用?
答案:
| 场景 | 说明 |
|---|---|
| 撤销/重做 | 编辑器、画板、表单 |
| 任务队列 | 异步执行、延迟执行 |
| 宏命令 | 批量操作 |
| 事务日志 | 操作记录与回放 |