初识设计模式——命令模式(Command Pattern)

cuixiaogang

命令模式(Command Pattern)是一种行为设计模式,它把请求封装成一个对象,从而允许你用不同的请求对客户进行参数化,对请求排队或记录请求日志,以及支持可撤销的操作。

命令模式的构成

  • 命令(Command):定义了执行操作的接口,通常包含一个执行方法execute()。
  • 具体命令(Concrete Command):实现了命令接口,负责调用接收者的相应操作。
  • 接收者(Receiver):知道如何执行与请求相关的操作,是实际执行命令的对象。
  • 调用者(Invoker):负责调用命令对象执行请求,不关心命令的具体实现。
  • 客户端(Client):创建具体命令对象,并设置其接收者,然后将命令对象传递给调用者。

命令模式结构图

案例

场景

在一个 Web 应用中,我们可能需要处理用户的不同操作,例如用户点击按钮时执行不同的业务逻辑。这里以用户点击 “保存” 和 “删除” 按钮为例,使用命令模式来实现。

代码

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
<?php
// 接收者类,负责具体的业务逻辑
class ArticleService {
public function save() {
echo "文章已保存\n";
}

public function delete() {
echo "文章已删除\n";
}
}

// 命令接口
interface Command {
public function execute();
}

// 具体命令类:保存文章
class SaveArticleCommand implements Command {
private $articleService;

public function __construct(ArticleService $articleService) {
$this->articleService = $articleService;
}

public function execute() {
$this->articleService->save();
}
}

// 具体命令类:删除文章
class DeleteArticleCommand implements Command {
private $articleService;

public function __construct(ArticleService $articleService) {
$this->articleService = $articleService;
}

public function execute() {
$this->articleService->delete();
}
}

// 调用者类
class ButtonInvoker {
private $command;

public function setCommand(Command $command) {
$this->command = $command;
}

public function click() {
$this->command->execute();
}
}

// 客户端代码
$articleService = new ArticleService();
$saveCommand = new SaveArticleCommand($articleService);
$deleteCommand = new DeleteArticleCommand($articleService);

$button = new ButtonInvoker();

// 模拟用户点击保存按钮
$button->setCommand($saveCommand);
$button->click();

// 模拟用户点击删除按钮
$button->setCommand($deleteCommand);
$button->click();

UML类图

UML类图

命令模式的适用场景

  • 需要对请求进行记录、排队、撤销、重做等操作:例如,在文本编辑器中,撤销和重做功能可以通过命令模式来实现。
  • 需要将请求的发送者和接收者解耦:当发送者和接收者之间的关系复杂,或者发送者不关心接收者的具体实现时,可以使用命令模式。
  • 需要在不同的时间指定、排列和执行请求:例如,在任务调度系统中,可以使用命令模式来管理和执行任务。

命令模式的优缺点

优点

  • 解耦:将请求的发送者和接收者解耦,提高了系统的可扩展性和可维护性。
  • 可扩展性:可以很容易地添加新的命令类,而不需要修改现有的代码。
  • 支持撤销和重做:可以方便地实现命令的撤销和重做功能。
  • 日志记录:可以记录命令的执行历史,方便后续的审计和调试。

缺点

  • 类的数量增加:每个具体命令都需要一个对应的类,会导致类的数量增加,增加了系统的复杂性。
  • 实现复杂:对于简单的操作,使用命令模式可能会增加代码的复杂度。