模式简介
命令模式是一种行为型设计模式,用于将对一个对象的操作或请求封装成单独的命令对象,使得命令可以用来存储、传递和管理,从而对调用者和被调用者进行解耦。为了方便管理,这些被封装的命令对象会实现统一的接口或者继承统一的基类,这样不仅使得调用者的调用逻辑更简洁,也可以实现对命令的组合使用。
常见的应用场景:GUI操作、文件操作、数据库事务、遥控器、日程调度系统、多级撤销、游戏开发和日志系统等。
模式结构
-
Command(命令接口): 定义执行操作的接口,通常包含
execute
方法。 -
ConcreteCommand(具体命令): 实现命令接口,负责具体的操作。它通常会持有一个接收者对象,并调用接收者的方法来执行操作。
-
Client(客户端): 创建一个具体命令对象,并将其关联到一个调用者对象上。
-
Invoker(调用者): 负责调用命令对象执行请求。
-
Receiver(接收者): 知道如何执行实际的操作,是具体命令所要操作的对象。
工作原理
-
客户端创建命令对象: 客户端创建一个具体命令对象,并设置其接收者,将操作封装成命令对象。
-
客户端设置命令对象: 将命令对象设置到调用者(Invoker)上,这样调用者就知道要执行哪个命令。
-
调用者执行命令: 当调用者需要执行某个操作时,它会调用命令对象的
execute
方法。 -
命令对象调用接收者: 具体命令对象收到调用后,会调用接收者的方法,执行实际的操作。
-
接收者执行操作: 接收者是实际执行操作的对象,它知道如何执行具体的操作。
代码示例(C#)
提示:请在本栏目的资源篇“设计模式代码示例合集”中下载所有完整代码资源。
命令:Command.cs
namespace CommandPattern;
// 命令
interface ICommand
{
// 执行
void Excute();
}
// 开灯
class TurnOnLight : ICommand
{
private Light light; // 灯
public TurnOnLight(Light light)
{
this.light = light;
}
public void Excute()
{
light.TurnOn();
}
}
// 关灯
class TurnOffLight : ICommand
{
private Light light; // 灯
public TurnOffLight(Light light)
{
this.light = light;
}
public void Excute()
{
light.TurnOff();
}
}
灯:Light.cs
namespace CommandPattern;
// 灯
class Light
{
// 是否处于打开状态
public bool isOn { get; private set; }
// 打开
public void TurnOn()
{
isOn = true;
Console.WriteLine("开灯...");
}
// 关闭
public void TurnOff()
{
isOn = false;
Console.WriteLine("关灯...");
}
}
控制器:Controller.cs
namespace CommandPattern;
#pragma warning disable
// 灯的开关控制按钮
class LightController
{
private ICommand command;
public LightController()
{
command = null;
}
// 设置按下按钮时执行的命令
public void SetCommand(ICommand command)
{
this.command = command;
}
// 按下按钮
public void PressButton()
{
if (command != null) command.Excute();
}
}
测试代码:Program.cs
// ************* 19.命令模式测试 **************
using CommandPattern;
// 创建实例
Light light = new Light();
TurnOnLight turnOn = new TurnOnLight(light);
TurnOffLight turnOff = new TurnOffLight(light);
LightController controller = new LightController();
// 开灯
controller.SetCommand(turnOn);
controller.PressButton();
Console.WriteLine("Light is On:" + light.isOn);
// 关灯
controller.SetCommand(turnOff);
controller.PressButton();
Console.WriteLine("Light is On:" + light.isOn);
代码解说
上述代码模拟了用开关按钮控制灯。对于灯而言有开和关两个状态,对应着开关按钮的开灯命令和关灯命令,开关按钮作为命令发起者,灯则作为命令接收者,两种命令将灯的状态改变逻辑封装起来并作为参数传递给开关按钮,使得开关按钮具备了开灯和关灯的功能。
如果这篇文章对你有帮助,请给作者点个赞吧!