简介
命令模式(Command Pattern)是一种数据驱动的设计模式,它属于行为型模式。请求以命令的形式包裹在对象中,并传给调用对象。调用对象寻找可以处理该命令的合适的对象,并把该命令传给相应的对象,该对象执行命令。
角色
-
发起者(Invoker):这是请求的发起者,它知道如何调用命令对象以执行请求。发起者通常不直接执行请求,而是将请求传递给命令对象。
-
命令(Command):这是命令模式的核心角色。命令对象封装了接收者应该执行的操作。它通常包含一个执行方法,用于在需要时调用接收者的相应方法。
-
接收者(Receiver):接收者是实际执行请求的对象。它实现了与命令对象相对应的操作。在命令模式中,接收者通常不知道关于命令或发起者的任何信息。
-
调用者(Caller):调用者是负责创建和调用命令对象的对象。它通常根据某些条件或事件来决定创建和执行命令对象。
-
客户端(Client):客户端是使用命令模式的用户或程序的一部分。它创建发起者和命令对象之间的连接,并可能根据需要传递参数或配置信息。
优点
- 解耦发送者和接收者
- 支持撤销和重做
- 支持队列和批处理
- 增强可扩展性
- 增强可维护性
- 支持日志和审计
缺点
- 增加类的数量
- 增加内存消耗
- 复杂性提高
应用场景
- 撤销和重做功能
- 菜单和工具栏
- 任务调度
- 日志记录
- 批处理
- 遥控器
- 数据库事务
- 网络请求队列
- 游戏开发
实现
- 定义命令接口
public interface ICommand
{
void Execute();
}
- 实现接口
public class ConcreteCommand : ICommand
{
private readonly Receiver _receiver;
public ConcreteCommand(Receiver receiver)
{
_receiver = receiver;
}
public void Execute()
{
_receiver.ActionToPerform(); // 调用接收者的具体操作方法
}
}
- 接收者
public class Receiver
{
public void ActionToPerform()
{
// 这里是接收者要执行的具体操作逻辑
Console.WriteLine("Receiver's action performed.");
}
}
- 调用者
public class Invoker
{
private ICommand _command;
public void SetCommand(ICommand command)
{
_command = command;
}
public void ExecuteCommand()
{
_command?.Execute(); // 安全地执行命令,如果命令为null则不执行任何操作。
}
}
- 上层应用调用
class Program
{
static void Main(string[] args)
{
// 创建接收者实例(被请求的对象)
var receiver = new Receiver();
// 创建具体命令实例,并将接收者传入作为依赖。
var command = new ConcreteCommand(receiver);
// 创建调用者实例,并将命令设置给它。
var invoker = new Invoker();
invoker.SetCommand(command);
// 通过调用者执行命令。 实际上会调用接收者的ActionToPerform方法。
invoker.ExecuteCommand(); // 这将触发命令的执行,从而调用接收者的操作。 输出 "Receiver's action performed." 到控制台。
}
}
在这个案例中,ConcreteCommand
是具体命令类,它知道如何根据接收者的状态来执行操作。Invoker
是调用者,它持有对命令的引用并负责在适当的时候执行这个命令。Receiver
是接收命令的对象,它包含了执行具体操作的逻辑。通过这种方式,你可以灵活地添加新的命令和接收者,而调用者的代码不需要改变。这就是命令模式的基本实现。