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、命令对象可以直接实现请求,不用将工作委托给接收者

  • 相关阅读:
    021-python基础-python介绍及课程简介
    020-python函数和常用模块-文件操作
    019-python函数和常用模块-内置函数
    018-python基础-三元运算和lambda表达式
    017-python函数和常用模块-函数式编程实现登陆和注册
    016-python函数和常用模块-函数定义和使用
    015-python基础-深浅拷贝
    014-python基础-set集合
    013-python基础-课堂练习
    012-python基础-数据运算
  • 原文地址:https://www.cnblogs.com/liumengchen-boke/p/8018389.html
Copyright © 2011-2022 走看看