设计模式之命令模式

命令模式可将"动作的请求者"从"动作的执行者"对象中解耦。
在设计中,采用"命令对象",利用命令对象,把请求封装成一个特定的对象,如果每个按钮都存储一个命令对象,那么当按钮被按下的时候,就可以请命令对象做相关工作了。

第一个命令对象

实现命令接口

    /// <summary>
    /// 实现命令接口:让所有命令对象实现相同的包含一个方法的接口
    /// </summary>
    public interface Command
    {
        void execute();
    }

实现一个打开电灯的命令

 public class LightOnCommand : Command
    {
        private Light light;

        public LightOnCommand(Light light)//构造方法中传入一个对象,当execute被调用的时候,就由这个对象作为接收者,接受请求。
        {
            this.light = light;
        }
        public void execute()//调用接收对象
        {
            light.@on();
        }
    }

使用命令对象

public  class SimpleRemoteControl
 {
     private Command slot;//插槽持有命令,这个命令控制着一个装置

     public SimpleRemoteControl()
     {
         
     }

     public void setCommand(Command command)//用来设置插槽控制的命令
     {
         slot = command;
     }

     public void buttonWasPressed()//调用这个方法,使得当前命令衔接插槽被调用
     {
         slot.execute();
     }
 }

简单测试

static void Main(string[] args)
        {
            SimpleRemoteControl remote=new SimpleRemoteControl();//发出请求
            Light light=new Light();//请求的接收者
            LightOnCommand lightOn=new LightOnCommand(light);//创建一个命令,将接收者传给它

            remote.setCommand(lightOn);//把命令传给调用者
            remote.buttonWasPressed();//调用
            Console.ReadKey();
        }

定义命令模式

命令模式:将请求封装成对象,以便使用不同请求、队列、或者日志来参数化其他对象。命令模式也支持可撤销操作。
一个命令对象通过在特定接收者上绑定一组动作来封装一个请求。命令对象将动作和接收者包进对象中,这个对象只暴漏出一个execute()方法,当此方法被调用的时候,接收者就会进行这些动作。

类图


client:这个客户负责创建一个ConcreteCommand,并设置其接收者。
Receiver:接收者知道如何进行必要的工作,实现这个请求。任何类都可以当接收者。
ConcreteCommand:这个ConcreteCommand定义了动作和接收者之间的绑定关系。
Invoker:这个调用者持有一个命令对象,并在某个时间点调用命令对象的execute方法,将请求实行。
Command:Command为所有命令声明了一个接口。调用命令对象的execute方法,就可以让接收者进行相关的动作。

使用反转命令

使用命令模式,我们还可以使用反转命令,撤销之前操作。

新增undo()

在命令接口中,新增undo()用于反转之前操作命令

    public interface Command
    {
        void execute();

        void undo();
    }

执行

public class LightOnCommand : Command
    {
        private Light light;

        public LightOnCommand(Light light)//构造方法中传入一个对象,当execute被调用的时候,就由这个对象作为接收者,接受请求。
        {
            this.light = light;
        }
        public void execute()//调用接收对象
        {
            light.@on();
        }

        public void undo()
        {
            light.off();
        }
    }

队列请求

命令可以将运算块打包,然后将它传来传去,就像是一般的对象一样。即使在命令对象被创建许久以后,运算依然可以被调用。这样就可以将它传入队列中使用。
队列对象不在乎到底做些什么,它们只知道取出命令对象,然后调用其execute()方法。

日志请求

某些应用需要我们将所有的动作都记录在日志中,并能在系统死机之后,重新调用这些动作恢复到之前的状态。
做法:当我们执行命令的时候,将历史记录存储在磁盘中,一旦系统死机,我们就可以将命令对象重新加载,并成批地依次调用这些对象的execute()方法。
通过使用记录日志,我们可以将上次检查点之后的所有操作记录下来,如果系统出现状况,从检查点开始应用这些操作。

原文地址:https://www.cnblogs.com/Tan-sir/p/8310860.html