命令模式
概述
将一个请求封装为一个对象,从而使你可用不同的请求对客户端进行参数化。对请求排队或记录请求日志,以及支持可撤销的操作
结构图
代码实现
命令
////// 抽象命令类 /// public abstract class Command { protected Receiver receiver; public Command(Receiver receiver) { this.receiver = receiver; } abstract public void Execute(); }
////// 具体命令实现 /// public class ConcreteCommand : Command { public ConcreteCommand(Receiver receiver) : base(receiver) { } public override void Execute() { receiver.Action(); } }
请求者
////// 请求者/调用者 /// public class Invoker { private Command command; public void SetCommand(Command command) { this.command = command; } public void ExecuteCommand() { command.Execute(); } }
接收者
////// 抽象接收者/实现者 /// public abstract class Receiver { public abstract void Action(); }
////// 接收者A/实现者A /// public class ReceiverA: Receiver { public override void Action() { Console.WriteLine("A执行请求!"); } }
////// 接收者B/实现者B /// public class ReceiverB : Receiver { public override void Action() { Console.WriteLine("B执行请求!"); } }
客户端
class Program { static void Main(string[] args) { Receiver rA = new ReceiverA(); Command cA = new ConcreteCommand(rA); Receiver rB = new ReceiverB(); Command cB = new ConcreteCommand(rB); Invoker i = new Invoker(); i.SetCommand(cA); i.ExecuteCommand(); i.SetCommand(cB); i.ExecuteCommand(); Console.Read(); } }
运行结果
优势
降低了系统耦合度。扩展性良好,增加或删除命令非常方便。采用命令模式增加与删除命令不会影响其他类,且满足“开闭原则”。
新的命令可以很容易添加到系统中去。
使用场景
软件系统中,行为请求者与行为实现者通常是一种紧耦合的关系,但某些场合,比如需要对行为进行记录、撤销或重做、事务等处理时。
当系统的某项操作具备命令语义,且命令实现不稳定(变化)时,可以通过命令模式解耦请求与实现。
请求调用者需要与请求接收者解耦时,命令模式可以使调用者和接收者不直接交互。
缺陷
使用命令模式可能会导致某些系统有过多的具体命令类。
Demo