命令模式(Command Pattern)将一个请求封装为一个对象,进而将拥有不同的请求的物体参数化,并且还可以请求排队,打印请求日志,支持可逆操作。

命令模式由抽象命令类、具体命令类、接受者、调用者、客户类,五部分组成。其中接受者为被命令封装的类,调用者存放需要执行的类。

我们以一个远程控制装置作为例子,远程控制装置有两个按钮和一个撤回按钮。我们通过命令模式来将远程控制类与具体需要做的操作(如开灯)解耦。在例子中程序入口即为客户端,远程装置为调用者,灯为接受者,有开灯与关灯两个命令

#代码示例

#抽象命令类及实现

抽象命令类
1
2
3
4
5
public interface Command
{
void Execute();
void Undo();
}
命令类实现
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
public class LightOffCommand : Command
{
private Light light;
public LightOffCommand(Light light)
{
this.light = light;
}
public void Execute()
{
light.Off();
}

public void Undo()
{
light.On();
}
}

public class LightOnCommand : Command
{
private Light light;
public LightOnCommand(Light light)
{
this.light = light;
}
public void Execute()
{
light.On();
}

public void Undo()
{
light.Off();
}
}

public class NoCommand : Command
{
public void Execute()
{
Console.WriteLine("No command execute");
}

public void Undo()
{
Console.WriteLine("No command undo");
}
}

#接受者

1
2
3
4
5
6
7
8
9
10
11
12
public class Light
{
public void On()
{
Console.WriteLine("The light is on");
}

public void Off()
{
Console.WriteLine("The light is off");
}
}

#调用者

远程控制
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
class RemoteControl
{
Command[] commands;
Command lastCommond;

public RemoteControl()
{
commands = new Command[2] { new NoCommand(), new NoCommand() };
lastCommond = new NoCommand();
}

public void SetCommand(int index, Command command)
{
commands[index] = command;
}

public void OnButtonClick(int index)
{
commands[index].Execute();
lastCommond = commands[index];
}

public void OnClickUndo()
{
lastCommond.Undo();
lastCommond = new NoCommand();
}
}

#客户类

函数入口
1
2
3
4
5
6
7
8
9
10
static void Main(string[] args)
{
Light light = new Light();
RemoteControl remoteControl = new RemoteControl();
remoteControl.SetCommand(0, new LightOnCommand(light));
remoteControl.SetCommand(1, new LightOffCommand(light));
remoteControl.OnButtonClick(0);
remoteControl.OnButtonClick(1);
remoteControl.OnClickUndo();
}

#测试及结果

运行结果:

命令模式测试结果