首页 > 代码库 > 用最简单的例子理解命令模式(Command Pattern)

用最简单的例子理解命令模式(Command Pattern)

假设想让遥控器控制电灯的开关、电视机的开关和切换,该如何做?

 

所有的开、关、切换都是遥控器发出的指令,把这些指令统一抽象成一个接口。

    public interface IControl
    {
        void Execute();
    }

 

把电灯、电视机抽象成类。

    public class Tv
    {
        public void TurnOn()
        {
            Console.WriteLine("电视机打开了");
        }
        public void TurnOff()
        {
            Console.WriteLine("电视机关闭了");
        }
        public void SwitchChannel()
        {
            Console.WriteLine("电视机切换频道");
        }
    }
    public class Light
    {
        public void TunrOn()
        {
            Console.WriteLine("电灯打开了");
        }
        public void TurnOff()
        {
            Console.WriteLine("电灯关闭了");
        }
    }

 

Tv类的TurnOn(),TurnOff(),SwitchChannel(),Light类的TurnOn(),TurnOff(),这些方法都会通过执行IController的Execute方法被触发。把每一种动作抽象成类,并实现IControl接口。

    public class LighOn : IControl
    {
        private Light _light;
        public LighOn(Light light)
        {
            _light = light;
        }
        public void Execute()
        {
            _light.TunrOn();
        }
    }
    public class LightOff : IControl
    {
        private Light _light;
        public LightOff(Light light)
        {
            _light = light;
        }
        public void Execute()
        {
            _light.TurnOff();
        }
    }
    public class TvOn : IControl
    {
        private Tv _tv;
        public TvOn(Tv tv)
        {
            _tv = tv;
        }
        public void Execute()
        {
            _tv.TurnOn();
        }
    }
    public class TvOff : IControl
    {
        private Tv _tv;
        public TvOff(Tv tv)
        {
            _tv = tv;
        }
        public void Execute()
        {
            _tv.TurnOff();
        }
    }
    public class TvSwitch : IControl
    {
        private Tv _tv;
        public TvSwitch(Tv tv)
        {
            _tv = tv;
        }
        public void Execute()
        {
            _tv.SwitchChannel();
        }
    }        

现在,电视机和电灯有了,触发各种动作的类有了,遥控器该装下这些指令(提供装下指令的方法)并提供方法供客户端调用。

    public class RemoteControl
    {
        private IList<IControl> onCommands = new List<IControl>();
        private IList<IControl> offCommands = new List<IControl>();
        private IList<IControl> switchCommands = new List<IControl>();
        public void AddOnCommand(IControl control)
        {
            onCommands.Add(control);
        }
        public void AddOffCommand(IControl control)
        {
            offCommands.Add(control);
        }
        public void AddSwitchCommand(IControl control)
        {
            switchCommands.Add(control);
        }
        public void PressOnButton(int number)
        {
            onCommands[number].Execute();
        }
        public void PressOffButton(int number)
        {
            offCommands[number].Execute();
        }
        public void PressSwitchButton(int number)
        {
            switchCommands[number].Execute();
        }
    }

 

客户端的执行逻辑大致是:把电视机、电灯准备好,把各种指令准备好,拿出遥控器把各种指令收纳其中,最后调用遥控器的方法执行各种指令。

    class Program
    {
        static void Main(string[] args)
        {
            //命令的接收方
            Light light = new Light();
            Tv tv = new Tv();
            //各种命令
            LighOn turnLightOn = new LighOn(light);
            LightOff turnLightOff = new LightOff(light);
            TvOn turnTvOn = new TvOn(tv);
            TvOff turnTvOff = new TvOff(tv);
            TvSwitch switchTv = new TvSwitch(tv);
            //RemoteConroller组装命令
            RemoteControl control = new RemoteControl();
            control.AddOnCommand(turnLightOn);
            control.AddOnCommand(turnTvOn);
            control.AddOffCommand(turnLightOff);
            control.AddOffCommand(turnTvOff);
            control.AddSwitchCommand(switchTv);
            control.PressOnButton(0);
            Console.ReadKey();
        }
    }

 

总结:命令模式的需求源自想通过一个指令(比如这里IControl的Execute方法)来控制多个类的多个方法,包含了几个要素:
1、命令:让类的各种方法抽象成类实现一个接口
2、装配命令:把各种命令放到一个集合中
3、触发命令:提供方法调用命令集合中的某条命令,让其执行指令
      

用最简单的例子理解命令模式(Command Pattern)