行为型模式之命令模式
概述
在软件开发中,我们经常需要向某些对象发送请求(调用其中的某个或某些方法),但是并不知道请求的接收者是谁,也不知道被请求的操作是哪个,此时,我们特别希望能够以一种松耦合的方式来设计软件,使得请求发送者与请求接收者能够消除彼此之间的耦合,让对象之间的调用关系更加灵活,可以灵活地指定请求接收者以及被请求的操作。命令模式为此类问题提供了一个较为完美的解决方案。
命令模式可以将请求发送者和接收者完全解耦,发送者与接收者之间没有直接引用关系,发送请求的对象只需要知道如何发送请求,而不必知道如何完成请求。
定义
命令模式(Command Pattern):将一个请求封装为一个对象,从而让我们可用不同的请求对客户进行参数化;对请求排队或者记录请求日志,以及支持可撤销的操作。命令模式是一种对象行为型模式,其别名为动作(Action)模式或事务(Transaction)模式。
实现
抽象命令类
public abstract class TVCommand { /// <summary> /// 电视机命令中持有一个电视机引用 /// </summary> protected Television _tv; public TVCommand() { this._tv = new Television(); } /// <summary> /// 执行命令的方法 /// </summary> public abstract void Excute(); }
开电视命令类
public class OpenTVCommand : TVCommand { public OpenTVCommand() { } /// <summary> /// 开电视 /// </summary> public override void Excute() { _tv.Open(); } }
关电视命令类
public class CloseTVCommand : TVCommand { public CloseTVCommand() { } /// <summary> /// 开电视 /// </summary> public override void Excute() { _tv.Close(); } }
换频道命令类
public class ChangeChannelCommand : TVCommand { public ChangeChannelCommand() { } /// <summary> /// 开电视 /// </summary> public override void Excute() { _tv.ChangeChannel(); } }
命令接受者-电视类
/// <summary> /// 请求接收者 /// </summary> public class Television { public void Open() { Console.WriteLine("打开电视机......"); } public void Close() { Console.WriteLine("关闭电视机......"); } public void ChangeChannel() { Console.WriteLine("切换电视频道......"); } }
命令发送者-遥控器类
/// <summary> /// 请求发送者,遥控器类 /// </summary> public class RemoteControl { private TVCommand openTVCommand; private TVCommand closeTVCommand; private TVCommand changeChannelCommand; public RemoteControl(TVCommand openTVCommand, TVCommand closeTVCommand, TVCommand changeChannelCommand) { this.openTVCommand = openTVCommand; this.closeTVCommand = closeTVCommand; this.changeChannelCommand = changeChannelCommand; } public void Open() { openTVCommand.Excute(); } public void Close() { closeTVCommand.Excute(); } public void ChangeChannel() { changeChannelCommand.Excute(); } }
客户端
class Program { static void Main(string[] args) { //命令发送者 RemoteControl control = new RemoteControl(new OpenTVCommand(), new CloseTVCommand(), new ChangeChannelCommand()); //发送命令 control.Open(); control.ChangeChannel(); control.Close(); Console.ReadLine(); } }
总结
命令模式是一种使用频率非常高的设计模式,它可以将请求发送者与接收者解耦,请求发送者通过命令对象来间接引用请求接收者,使得系统具有更好的灵活性和可扩展性。在基于GUI的软件开发,无论是在电脑桌面应用还是在移动应用中,命令模式都得到了广泛的应用。
主要优点
1、 降低系统的耦合度。由于请求者与接收者之间不存在直接引用,因此请求者与接收者之间实现完全解耦,相同的请求者可以对应不同的接收者,同样,相同的接收者也可以供不同的请求者使用,两者之间具有良好的独立性。
2、新的命令可以很容易地加入到系统中。由于增加新的具体命令类不会影响到其他类,因此增加新的具体命令类很容易,无须修改原有系统源代码,甚至客户类代码,满足“开闭原则”的要求。
3、 可以比较容易地设计一个命令队列或宏命令(组合命令)。
4、为请求的撤销(Undo)和恢复(Redo)操作提供了一种设计和实现方案。
主要缺点
使用命令模式可能会导致某些系统有过多的具体命令类。因为针对每一个对请求接收者的调用操作都需要设计一个具体命令类,因此在某些系统中可能需要提供大量的具体命令类,这将影响命令模式的使用。