把请求封装成一个对象,从而分离请求发起和执行。发起者和执行者之间通过命令对象进行沟通,便于请求对象的储存、传递、调用、增加和管理。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
class Command {
protected:
Application* app_;
Editor* editor_;
std::string backup_;
public:
Command(Application* app, Editor* editor): app_(app), editor_(editor) {}
void saveBackup() {
backup_ = editor_->text;
}
void undo() {
editor_->setText(backup_);
}
virtual bool execute() = 0;
};

class CopyCommand: public Command {
bool execute() override {
app_->setClipboard(editor_->getSelection());
return true;
}
};

class CutCommand: public Command {
bool execute() override {
saveBackup();
app_->setClipboard(editor_->getSelection());
editor_->deleteSelection();
return true;
}
};

class PasteCommand: public Command {
bool execute() override {
saveBackup();
editor_->replaceSelection(app->getClipboard());
return true;
}
};

class UndoCommand: public Command {
bool execute() override {
app_->undo();
return false;
}
};

class CommandHistory {
private:
std::vector<Command*> history_;
public:
void push(Command* c) {
history_.push_back(c);
}
Command* pop() {
if (history_.empty()) return nullptr;
Comman* cmd = history_.back();
history_.pop_back();
return cmd;
}
};

class Editor {
public:
std::string text_;
std::string getSelection() {
// get copy of selected text
}
void deleteSelection() {
// delete selected text
}
void replaceSelection(std::string text) {
// insert the contents at the current position
}
};

class Application {
public:
std::string clipboard_;
std::vector<Editor*> editors_;
Editor* activeEditor_;
CommandHistory history;

void createUI {
// create necessary elements

std::function<void()> copy = [this]() {
executeCommand(new CopyCommand(this, activeEditor_));
}
copyButton.setCommand(copy);
shortcuts.onKeyPress("ctrl+c", copy);

std::function<void()> cut = [this]() {
executeCommand(new CutCommand(this, activeEditor_));
}
cutButton.setCommand(cut);
shortcuts.onKeyPress("ctrl+x", cut);

std::function<void()> undo = [this]() {
executeCommand(new UndoCommand(this, activeEditor_));
}
undoButton.setCommand(undo);
shortcuts.onKeyPress("ctrl+z", undo);
}

void executeCommand(Command* c) {
if (c->execute()) history.push(c);
else delete c;
}

void undo() {
auto command = history.pop();
if (command) command->undo();
}
};