命令模式(Command Pattern)属于行为设计模式,它将请求或简单操作封装为一个对象。这种模式允许用户发出请求的同时,不必了解请求的具体操作或请求的接收者是谁。命令模式通常用于实现请求的排队、记录请求日志以及实现可撤销操作等功能。常常和备忘录模式一起使用,用于实现撤销功能,之后学到这了会在这里贴上链接。
核心组件
命令模式主要涉及以下几个角色:
- 命令(Command):定义所有具体命令类的接口。通常会声明一个执行命令的方法。
- 具体命令(Concrete Command):实现命令接口,定义了对请求接收者的调用行为。
- 请求者/调用者(Invoker):负责调用命令对象执行请求。
- 接收者(Receiver):执行与请求相关的操作。具体命令对象对该类的方法进行调用,以实现具体的操作。
- 客户端(Client):创建具体命令对象,并设置其接收者。
优点
- 解耦调用者和接收者:调用者和接收者之间没有直接联系,调用者只需要知道如何发送命令。
- 扩展性强:新增命令或者更改命令的实现不会影响现有的调用者代码。
- 支持撤销操作:可以通过实现一个撤销命令的方法来支持撤销操作。
- 易于实现操作的记录和分享:命令对象可以被序列化并持久化,从而允许操作的记录、撤销、重放或分享。
示例
假设我们有一个简单的文本编辑器,需要实现文本的剪切、复制和粘贴功能。我们可以使用命令模式来实现这些功能。
首先,定义Command
接口和Receiver
:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
|
// 命令接口
public interface ICommand
{
void Execute();
}
// 接收者
public class TextEditor
{
public void Cut()
{
Console.WriteLine("Cutting text");
}
public void Copy()
{
Console.WriteLine("Copying text");
}
public void Paste()
{
Console.WriteLine("Pasting text");
}
}
|
接下来,定义具体的命令:
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
|
// 具体命令
public class CutCommand : ICommand
{
private TextEditor _editor;
public CutCommand(TextEditor editor)
{
_editor = editor;
}
public void Execute()
{
_editor.Cut();
}
}
public class CopyCommand : ICommand
{
private TextEditor _editor;
public CopyCommand(TextEditor editor)
{
_editor = editor;
}
public void Execute()
{
_editor.Copy();
}
}
public class PasteCommand : ICommand
{
private TextEditor _editor;
public PasteCommand(TextEditor editor)
{
_editor = editor;
}
public void Execute()
{
_editor.Paste();
}
}
|
最后,实现Invoker
:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
|
public class CommandInvoker
{
private ICommand _command;
public void SetCommand(ICommand command)
{
_command = command;
}
public void ExecuteCommand()
{
_command.Execute();
}
}
|
客户端代码:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
|
class Program
{
static void Main(string[] args)
{
TextEditor editor = new TextEditor();
CommandInvoker invoker = new CommandInvoker();
invoker.SetCommand(new CutCommand(editor));
invoker.ExecuteCommand();
invoker.SetCommand(new CopyCommand(editor));
invoker.ExecuteCommand();
invoker.SetCommand(new PasteCommand(editor));
invoker.ExecuteCommand();
}
}
|
在这个例子中,TextEditor
是接收者,实现了剪切、复制和粘贴的实际操作;CutCommand
、CopyCommand
和PasteCommand
是具体的命令;CommandInvoker
是调用者,通过命令对象间接操作接收者。客户端通过设置调用者的命令对象来执行具体的操作,实现了调用者和接收者之间的解耦。