设计模式(十四)命令

一、定义

将一个请求封装为一个对象,从而可以用不同的请求对客户进行参数化,对请求排队或者记录请求日志,以及支持可撤销的操作。命令模式是一种对象行为型模式,其别名为动作(Action)模式或事物(Transaction)模式。

二、描述

命令模式的本质是对请求进行封装,一个请求对应一个命令,将发出命令的责任和执行命令的责任分割开,使得请求的一方不必了解接收请求的一方的接口,更不必知道请求如何被接收、操作是否被执行、何时被执行,以及是怎么被执行的。包含以下四个角色:设计模式(十四)命令
1、Command(抽象命令类):抽象命令类一般是一个抽象类或接口,在其中声明了用于执行请求的Execute()方法,通过这些方法可以调用请求接收者的相关操作。
2、ConcreteCommand(具体命令类):具体命令类是抽象命令类的子类,实现了抽象命令类中声明的方法,它对应具体的接收者对象,将接收者对象的动作绑定其中。具体命令类在实现Execute()方法时,将调用接收者对象的相关操作(Action)。
3、Invoker(调用者):调用者即请求发送者,它通过命令对象来执行请求。一个调用者不需要在设计时确定其接收者,因此只与抽象命令之间存在关联关系。在程序运行时可以将一个具体命令对象注入其中,再调用具体命令对象的Execute()方法,从而实现简介调用请求接收者的相关命令。
4、Receiver(接收者):接收者执行与请求相关的操作,具体实现对请求的业务处理。

三、例子

X公司开发人员开发了一个桌面版应用程序,该应用程序为员工提供了一系列自定义功能键,通过这些功能键来实现一些快捷操作,例如:“打开帮助文档”、“最小化至托盘”、“自动截屏”等。
设计模式(十四)命令FBSettingWindow:“功能键设置”界面类,充当客户端

public class FBSettingWindow {     // 窗口标题     public string Title { get; set; }     // 所有功能键集合     private IList<FunctionButton> functionButtonList = new List<FunctionButton>();      public FBSettingWindow(string title)     {         this.Title = title;     }      public void AddFunctionButton(FunctionButton fb)     {         functionButtonList.Add(fb);     }      public void RemoveFunctionButton(FunctionButton fb)     {         functionButtonList.Remove(fb);     }      // 显示窗口及功能键     public void Display()     {         Console.WriteLine("显示窗口:{0}", this.Title);         Console.WriteLine("显示功能键:");          foreach (var fb in functionButtonList)         {             Console.WriteLine(fb.Name);         }          Console.WriteLine("------------------------------------------");     } } 

FunctionButton:请求发送类,充当调用者

public class FunctionButton {     // 功能键名称     public string Name { get; set; }     // 维持一个抽象命令对象的引用     private Command command;      public FunctionButton(string name)     {         this.Name = name;     }      // 为功能键注入命令     public void SetCommand(Command command)     {         this.command = command;     }      // 发送请求的方法     public void OnClick()     {         Console.WriteLine("点击功能键:");         if (command != null)         {             command.Execute();         }     } } 

Command:抽象命令类

public abstract class Command {     public abstract void Execute(); } 

HelpCommand、MinimizeCommand:帮助类、最小化类,充当具体命令类

public class HelpCommand : Command {     private HelpHandler hander;      public HelpCommand()     {         hander = new HelpHandler();     }      // 命令执行方法,将调用请求接受者的业务方法     public override void Execute()     {         if (hander != null)         {             hander.Display();         }     } }  public class MinimizeCommand : Command {     private WindowHandler handler;      public MinimizeCommand()     {         handler = new WindowHandler();     }      // 命令执行方法,将调用请求接受者的业务方法     public override void Execute()     {         if (handler != null)         {             handler.Minimize();         }     } } 

WindowHandler、HelpHandler:最小化处理类、帮助处理类,充当接收者

public class WindowHandler {     public void Minimize()     {         Console.WriteLine("正在最小化窗口至托盘...");     } }  public class HelpHandler {     public void Display()     {         Console.WriteLine("正在显示帮助文档...");     } } 

Program:客户端测试类

//Step1.模拟显示功能键设置窗口 FBSettingWindow window = new FBSettingWindow("功能键设置窗口");  // Step2.假如目前要设置两个功能键 FunctionButton buttonA = new FunctionButton("功能键A"); FunctionButton buttonB = new FunctionButton("功能键B");  // Step3.读取配置文件和反射生成具体命令对象 Command commandA = new HelpCommand(); Command commandB = new MinimizeCommand();  // Step4.将命令注入功能键 buttonA.SetCommand(commandA); buttonB.SetCommand(commandB);  window.AddFunctionButton(buttonA); window.AddFunctionButton(buttonB); window.Display();  // Step5.调用功能键的业务方法 buttonA.OnClick(); buttonB.OnClick(); Console.ReadLine(""); 

设计模式(十四)命令

四、总结

1、优点

(1)降低了系统的耦合度,了系统的耦合度。由于请求者与接收者之间不存在直接引用,因此请求者与接收者之间实现了完全解耦,相同的请求者可以对应不同的接收者,同样,相同的接收者也可以供不同的请求者使用,两者之间具有良好的独立性。
(2)通过使用命令模式,新的命令可以很容易地加入到系统中。由于增加新的具体命令类不会影响其他类,所以增加新的具体命令类很容易,无须修改原有系统源代码,甚至客户类代码,满足开闭原则的要求。
(3)使用命令模式可以比较容易地设计一个命令队列或宏命令(组合命令)。
(4)命令模式为请求的撤销(Undo)和恢复(Redo)操作提供了一种设计和实现方案。

2、缺点

(1)使用命令模式可能会导致某些系统有过多的具体命令类,因为针对每一个对请求接收者的调用操作都需要设计一个具体命令,所以在某些系统中可能需要提供大量的具体命令类,这将影响命令模式的使用。

发表评论

评论已关闭。

相关文章