zoukankan      html  css  js  c++  java
  • 设计模式篇——初探命令模式

    命令模式介绍


    1、命令模式介绍:命令模式将“请求”封装成对象,以便使用不同的请求、队列或者日志来参数化其他对象。命令模式也支持可撤销的操作。


    PS:个人理解的命令模式就是将“请求”(方法)封装起来,这个请求中,存在一个或者多个接收者,然后把这个对象传递给一个Invoker(调用者)对象,并向外暴露出一个execute()方法,在特定的时刻调用这个execute方法,进而执行封装的请求方法。 这样做的优点就是外界不需要知道Receiver对象进行了哪些操作,我(外界)仅仅调用了execute方法而已;这样就实现了调用对象调用的请求者之间的解耦。

    2、命令模式类图

    先大致看看,脑袋里面有个大体印象~~~emmmmmmmm

    3、命令模式实例


    现在我们将要实现一个遥控器,用来控制电灯开关,车库门的上下、开关灯等操作。

    /// <summary>
    /// 定义请求对象接口,对外暴露方法Execute
    /// </summary>
    public interface ICommand
    {
        void Execute();
    }
    /// <summary>
    /// 定义一个电灯类,存在打开、关闭方法
    /// </summary>
    public class Light
    {
        public void On()
        {
            Console.WriteLine("灯打开了");
        }
        public void Off()
        {
            Console.WriteLine("灯关闭了");
        }
    }
    /// <summary>
    /// 电灯打开指令,继承ICommand接口
    /// </summary>
    public class LightOnCommand : ICommand
    {
        public Light _light;
        /// <summary>
        /// 构造函数传入电灯参数
        /// </summary>
        /// <param name="light"></param>
        public LightOnCommand(Light light)
        {
            _light = light;
        }
        /// <summary>
        /// Execute方法将执行电灯的打开操作
        /// </summary>
        public void Execute()
        {
            _light.On();
        }
    }
    /// <summary>
    /// 同理,来一个电灯关闭的指令
    /// </summary>
    public class LightOffCommand:ICommand
    {
        public Light _light;
        public LightOffCommand(Light light)
        {
            _light = light;
        }
        public void Execute()
        {
            _light.Off();
        }
    }
    /// <summary>
    /// 同理,定义一个车库对象
    /// </summary>
    public class GarageDoor
    {
        public void Up()
        {
            Console.WriteLine("车库门往上拉");
        }
        public void Down()
        {
            Console.WriteLine("车库门往下降");
        }
        public void Stop()
        {
            Console.WriteLine("车库门停止");
        }
        public void lightOn()
        {
            Console.WriteLine("车库灯打开");
        }
        public void lightOff()
        {
            Console.WriteLine("车库灯关闭");
        }
    }
    GarageDoor对象
    public class GarageDoorOpenCommand : ICommand
    {
        GarageDoor _garageDoor;
        public GarageDoorOpenCommand(GarageDoor garageDoor)
        {
            _garageDoor = garageDoor;
        }
        public void Execute()
        {
            _garageDoor.Up();
            _garageDoor.lightOn();
        }
    }
    public class GarageDoorCloseCommand : ICommand
    {
        GarageDoor _garageDoor;
        public GarageDoorCloseCommand(GarageDoor garageDoor)
        {
            _garageDoor = garageDoor;
        }
        public void Execute()
        {
            _garageDoor.Down();
            _garageDoor.lightOff();
        }
    }
    定义车库门操作对象,当然,要继承ICommand对象

    接下来让我们来定义一个遥控器:

      public class NoCommand : ICommand
        {
            public void Execute()
            {
                Console.WriteLine("这个操作是个空操作");
            }
        }
        /// <summary>
        /// 定义遥控器
        /// </summary>
        public class RemoteControl
        {
            ICommand[] _icommandOnList;        //一个ICommand 接口数组。 存放打开指令,理解为遥控器插槽 
            ICommand[] _icommandOffList;       //另一个ICommand 接口数组,存放关闭指令。理解为遥控器插槽
            public RemoteControl()
            {
                ICommand noCommand = new NoCommand();
                _icommandOnList = new ICommand[2] { noCommand, noCommand };     //默认将控制另放入"插槽"
                _icommandOffList = new ICommand[2] { noCommand, noCommand };
            }
            public void setCommand(int slot,ICommand onCommand,ICommand offCommand)  //将具体设备指令方法对应位置的插槽
            {
                _icommandOnList[slot] = onCommand;
                _icommandOffList[slot] = offCommand;
            }
            public void onButtonWasPushed(int slot)                                 //按下指定位置的按钮,执行指定打开命令
            {
                _icommandOnList[slot].Execute();
            }
            public void offButtonWasPushed(int slot)                                //按下指定位置的按钮,执行指定打开命令
            {
                _icommandOffList[slot].Execute();
            }
        }

     从开始我们就说,命令模式支持撤销操作,那现在让我们来加上撤销操作。

    修改ICommand接口、

    修改电灯和车库门的指令

    同理,电灯的关闭指令以及车库门相关指令

    接下来,修改遥控器类,添加一个“撤销插槽”

    好,这样我们就完成了,让我们来测试一下

     现在我们需要为遥控器添加一个宏命令。按下打开按钮的时候既可以开灯 又可以 拉起车库的门,同理,关闭按钮也可以执行所有的“关闭动作”

    首先,然我们来定义一个“宏命令”类,这个类用来执行一组命令或者撤销一组命令~

    public class MacroCommand:ICommand          //创建一个宏命令
    {
        ICommand[] _Commands;                   //用来存储一组命令
        public MacroCommand(ICommand[] Commands)     
        {
            _Commands = Commands;
        }
        public void Execute()                   //执行一组开的命令
        {
            foreach(var commnad in _Commands)
            {
                commnad.Execute();
            }
        }
        public void Undo()                      //执行一组撤销的命令
        {
            foreach (var commnad in _Commands)
            {
                commnad.Undo();
            }
        }
    }

    这时候我们需要把电灯,车库的相关命令,放入宏命令中;再把宏命令放入遥控器的插槽“0”中去

    NewCommand.RemoteControl remoteControl = new NewCommand.RemoteControl();  //遥控器
    NewCommand.Light roomlight = new NewCommand.Light();                      //电灯以及它的指令
    NewCommand.LightOnCommand roomLightOnCommand = new NewCommand.LightOnCommand(roomlight);
    NewCommand.LightOffCommand roomLightOffCommand = new NewCommand.LightOffCommand(roomlight);
    
    GarageDoor garageDoor = new GarageDoor();                                //车库门以及指令
    GarageDoorOpenCommand garageOpenCommand = new GarageDoorOpenCommand(garageDoor);
    GarageDoorCloseCommand garageCloseCommand = new GarageDoorCloseCommand(garageDoor);
    //把一组打开的命令放入放入宏命令
    MacroCommand onMacroCommand = new MacroCommand(new NewCommand.ICommand[] { roomLightOnCommand, garageOpenCommand });
    //把一组关闭的命令放入放入宏命令
    MacroCommand offMacroCommand = new MacroCommand(new NewCommand.ICommand[] { roomLightOffCommand, garageCloseCommand });
    remoteControl.setCommand(0, onMacroCommand, offMacroCommand); //宏命令放入遥控器插槽
    Console.WriteLine("打开宏命令");
    remoteControl.onButtonWasPushed(0);
    Console.WriteLine("关闭宏命令");
    remoteControl.offButtonWasPushed(0);
    Console.WriteLine("撤销宏命令");
    remoteControl.undoButtonWasPushed();

    让我们来测试下 =》

    最后来总结下命令模式:

    1、命令模式允许我们将动作封装成命令对象,这样我就可以随意存储,传递,调用它们。

    2、命令模式将请求者请求对象的执行者解耦,两者通过命令对象来进行沟通。

    3、调用者(接收者)通过调用命令对象的execute()方法(本例中)发出请求,请求对象的执行者执行相应的方法。

    4、调用者可以接受命令当做参数。

    5、命令可以支持撤销,方法是实现一个undo()方法(本例中),回到执行execute()执行前的状态

    6、宏命令允许调用多个命令,宏命令的撤销也能撤销多个命令。

    7、命令对象可以直接实现请求,不用将工作委托给接收者

  • 相关阅读:
    ABAP接口用法
    监听textarea数值变化
    The first step in solving any problem is recognizing there is one.
    Wrinkles should merely indicate where smiles have been.
    God made relatives.Thank God we can choose our friends.
    Home is where your heart is
    ABAP跳转屏幕
    Python 工具包 werkzeug 初探
    atom通过remote ftp同步本地文件到远程主机的方法
    Mongodb学习笔记一
  • 原文地址:https://www.cnblogs.com/liumengchen-boke/p/8018389.html
Copyright © 2011-2022 走看看