澳门新萄京官方网站-www.8455.com-澳门新萄京赌场网址

澳门新萄京官方网站命令格局,封装调用

2019-11-10 作者:www.8455.com   |   浏览(151)

正文的概念内容来自开头设计格局一书.

07 《Head First设计情势》 读书笔记07 封装调用:命令格局

一、   着力概述

项目要求

澳门新萄京官方网站 1

有这么三个可编制程序的新型遥控器, 它有7个可编制程序插槽, 各样插槽可延续分化的家用电器设备. 各类插槽对应八个按键: 开, 关(ON, OFF). 别的还会有三个大局的废除开关(UNDO).

于今客商想选用这些遥控器来决定不一致商家的小家电, 比如电灯, 磁能热水器, 风扇, 音响等等.

顾客提议让自家编写叁个接口, 能够让那么些遥控器调整插在插槽上的贰个或后生可畏组设备.

看一下当下各家厂家都有如何家电:

澳门新萄京官方网站 2

难题来了, 这个家用电器并未有合营的标准....大致各自都有友好的生龙活虎套调控方法.. 而且其后还要加上比非常多种家电.

 

  问题:假使有贰个调节器,该调节器上有7个可编制程序的插槽,各种都能够钦命到叁个不及的家用电器装置,每种插槽都有对应的按钮开关。这几个遥控器还具有二个整机的打消开关。厂商已经提供了调整家电基本管理类。希望你能够成立风流洒脱组决定遥控器的API,让每种插槽都能够决定一个或生龙活虎组织设立置。(如下图,商家类卡塔尔国

设计思路

那就须要思虑一下解决方案了:

先是要考虑分开关切点(Separation of concerns),  遥控器应该能够降解按键动作并得以发送必要, 可是它不应有明白家电和怎么按钮家电等.

只是近期遥控器只好做按键效能, 那么怎么让它去决定电灯也许音响呢? 大家不想让遥控器知道那些实际的家电, 更不想写出下边包车型客车代码:

if slot1 == Light then Light.On()
else if slot1 == Hub....

聊到那就只可以提到命令形式(Command Pattern)了.

命令方式允许你把动作的哀求者和动作的实在试行者解耦. 这里, 动作的央求者就是遥控器, 而试行动作的靶子正是某些家用电器.

那是怎么解耦的吧? 怎么恐怕达成吗?

那就须要引入"命令对象(command object)"了. 命令对象会封装在有个别对象上(例如卧房的灯)试行某些动作的央求(比方开灯). 所以, 纵然大家为每多个按键都筹划叁个发令对象, 那么当开关被按下的时候, 大家就能调用那一个命令对象去施行有个别动作. 遥控器本人并不知器械体实行的动作是怎样, 它只是有贰个指令对象, 那么些命令对象掌握去对什么电器去做什么的操作. 就那样, 遥控器和电灯解耦了.

题目引进

  有叁个黏附多组开关按键的遥控器,带有可编制程序插槽,各样都得以内定到一个两样的家用电器装置;有成都百货上千厂家开采的各类家电装置调控类;希望创建生机勃勃组API,让每一种插槽调控五个或风流倜傥组织设立置。

  寻思:不应有让遥控器知道太多厂家类的底细,不然更加多的家用电器加进去,就一定要修正代码。

 澳门新萄京官方网站 3

三个命令方式的实际例子

三个快餐厅:

澳门新萄京官方网站 4

客商给推销员订单, 前台经理把订单放到柜台并说: "有新订单了", 然后厨神遵照订单筹划饭菜.

让我们精心深入分析一下它们是怎么人机联作的:

澳门新萄京官方网站 5

客商来了, 说自个儿想要埃及开罗, 奶酪....便是开创了一个订单 (createOrder()).

订单上边写着客商想要的饭菜. 

侍者拿到订单 takeOrder(), 把订单得到柜台喊道: "有新订单了" (调用orderUp())

炊事员根据订单的提醒把饭菜做好 (orderUp()里面包车型客车动作). 

 

剖析一下以此例子的剧中人物和职务:

  • 订单里封装了做饭菜的央浼. 能够把订单想象成叁个目的, 那么些目标好似对起火这几个动作的诉求. 并且它能够来回传递. 订单达成了八个只有orderUp()方法的接口, 这几个方法里面封装了做饭的操作流程. 订单並且对动作施行者的援用(厨神). 因为都打包了, 所以服务生不晓得订单里面有吗也不精通厨子是什么人. 推销员只传递订单, 并调用orderUp().
  • 进而, 服务员的行事正是传递订单并且调用orderUp(). 服务生的取订单takeOrder()方法会传进来不一致的参数(不相同客商的例外订单), 不过那不是主题材料, 因为她驾驭全部的订单都扶助orderUp()方法.
  • 炊事员知道怎么把饭做好. 大器晚成旦前台经理调用了orderUp(), 厨子就接管了上上下下工作把饭菜做好. 可是推销员和厨师是解耦的: 看板娘唯有订单, 订单里封装着饭菜, 服务生只是调用订单上的一个方法而已. 相仿的, 厨神只是从订单上采纳斯达克综合指数令, 他不曾和服务员风度翩翩直接触.

 

  分析1:厂家提供的类,有过多都负有On()和off()方法,除此之外还恐怕有部分别样的美妙绝伦的艺术。

花色设计图

再次回到我们的须求, 参谋快餐店的例证, 使用命令情势做一下两全:

澳门新萄京官方网站 6

客商Client成立了三个指令(Command)对象. 也便是别人拿起了二个订单(点菜)希图上马点菜, 作者在雕琢遥控器的槽须求插哪些家电. 命令对象和采用者是绑定在一块儿的. 也正是菜单和厨神, 遥控器的插槽和指标家电.

指令对象唯有叁个方法execute(), 里面封装了调用接受者实际决定操作的动作. 约等于饭馆订单的orderUp().

客户调用setCommand()方法. 也正是顾客想好点什么菜了, 就写在订单下面了. 笔者也想好遥控器要调节什么家用电器了, 列好清单了. 

调用者拿着曾经setCommand的命令对象, 在今后某些时间点调用命令对象方面包车型客车execute()方法. 相当于服务生拿起订单走到柜台前, 大喊一声: "有订单来了, 开端做菜吧". 约等于自个儿把遥控器和设备的接口连接上了, 酌量上马调节.

最后接纳者试行动作. 也正是厨神做饭. 家电使用自身唯有的决定方法进行动作.

这里面:

客商 --- 商旅客人, 小编

命令 --- 订单, 插槽

调用者 --- 服务员, 遥控器

setCommand()设置命令 --- takeOrder() 取订单, 插上急需调整的电器

execute() 推行 ---  orderUp() 告诉柜台做饭, 按按键

接收者 --- 厨师, 家电

焚林而猎方案

  使用一声令下方式,将动作的央求者从动作的实行者对象中解耦。

  在该难点中,央浼者能够是遥控器,而实践者对象就是厂家类当中之风流倜傥的实例。

  利用“命令对象”,把必要封装成二个一定对象,各个按键都存款和储蓄二个限令对象,当开关被按下的时候,就足以请命令对象做相关的工作。

  遥控器并无需知道专行业内部容是何许,只要有个指令对象能和不错的靶子关联,把工作办好就能够了。

  分析2:还不只那样,听上去如同未来还恐怕有更加多的商家类,而且各个类还有丰裕多采的措施。

代码实行

抱有命令对象急需落到实处的接口:

namespace CommandPattern.Abstractions
{
    public interface ICommand
    {
        void Execute();
    }
}

一盏灯:

using System;

namespace CommandPattern.Devices
{
    public class Light
    {
        public void On()
        {
            Console.WriteLine("Light is on");
        }

        public void Off()
        {
            Console.WriteLine("Light is off");
        }
    }
}

控制灯张开的一声令下:

using CommandPattern.Abstractions;
using CommandPattern.Devices;

namespace CommandPattern.Commands
{
    public class LightOnCommand : ICommand
    {
        private readonly Light light;

        public LightOnCommand(Light light)
        {
            this.light = light;
        }

        public void Execute()
        {
            this.light.On();
        }
    }
}

车库门: 

using System;

namespace CommandPattern.Devices
{
    public class GarageDoor
    {
        public void Up()
        {
            Console.WriteLine("GarageDoor is opened.");
        }

        public void Down()
        {
            Console.WriteLine("GarageDoor is closed.");
        }
    }
}

收起车库门命令:

using CommandPattern.Abstractions;
using CommandPattern.Devices;

namespace CommandPattern.Commands
{
    public class GarageDoorOpen : ICommand
    {
        private readonly GarageDoor garageDoor;

        public GarageDoorOpen(GarageDoor garageDoor)
        {
            this.garageDoor = garageDoor;
        }

        public void Execute()
        {
            garageDoor.Up();
        }
    }
}

简言之的遥控器:

using CommandPattern.Abstractions;

namespace CommandPattern.RemoteControls
{
    public class SimpleRemoteControl
    {
        public ICommand Slot { get; set; }
public void ButtonWasPressed()
        {
            Slot.Execute();
        }
    }
}

运转测验:

using System;
using CommandPattern.Commands;
using CommandPattern.Devices;
using CommandPattern.RemoteControls;

namespace CommandPattern
{
    class Program
    {
        static void Main(string[] args)
        {
            var remote = new SimpleRemoteControl();
            var light = new Light();
            var lightOn = new LightOnCommand(light);

            remote.Slot = lightOn;
            remote.ButtonWasPressed();

            var garageDoor = new GarageDoor();
            var garageDoorOpen = new GarageDoorOpenCommand(garageDoor);

            remote.Slot = garageDoorOpen;
            remote.ButtonWasPressed();
        }
    }
}

澳门新萄京官方网站 7

 

  分析3:遥控器应该领悟怎么解读按键被按下的动作,然后发出正确的乞请,但是遥控器不需清楚这一个家电自动化的内幕。

指令形式定义

命令形式把央浼封装成三个指标, 进而能够运用分化的伸手对任何对象开展参数化, 对诉求排队, 记录伏乞的历史, 并辅助撤销操作.

类图:

澳门新萄京官方网站 8

效果图:

澳门新萄京官方网站 9

用实例证实

  在茶楼,客商将团结的供给写在订单上,由前台经理交给大厨,然后厨神遵照订单指令计划餐点。

  分析4:小编们不想让遥控器包蕴一大堆if语句,比方“if slot1==Light,then light.On(),else if slot1==Hottub,then hottub.JetsOn()”.我们都掌握这么的安排性特不佳。且大器晚成旦有新的厂家类进来,就非得修正现存的代码,造成潜在的失实。

全职能代码的实践

遥控器:

using System.Text;
using CommandPattern.Abstractions;
using CommandPattern.Commands;

namespace CommandPattern.RemoteControls
{
    public class RemoteControl
    {
        private ICommand[] onCommands;
        private ICommand[] offCommands;

        public RemoteControl()
        {
            onCommands = new ICommand[7];
            offCommands = new ICommand[7];

            var noCommand = new NoCommand();
            for (int i = 0; i < 7; i  )
            {
                onCommands[i] = noCommand;
                offCommands[i] = noCommand;
            }
        }

        public void SetCommand(int slot, ICommand onCommand, ICommand offCommand)
        {
            onCommands[slot] = onCommand;
            offCommands[slot] = offCommand;
        }

        public void OnButtonWasPressed(int slot)
        {
            onCommands[slot].Execute();
        }
        public void OffButtonWasPressed(int slot)
        {
            offCommands[slot].Execute();
        }

        public override string ToString()
        {
            var sb = new StringBuilder("n------------Remote Control-----------n");
            for(int i =0; i< onCommands.Length; i  ){
                sb.Append($"[slot{i}] {onCommands[i].GetType()}t{offCommands[i].GetType()} n");
            }
            return sb.ToString();
        }
    }
}

这么些中有多个NoCommand, 它是八个空的类, 只是为了开首化command 以便现在不要判定是不是为null.

关灯:

using CommandPattern.Abstractions;
using CommandPattern.Devices;

namespace CommandPattern.Commands
{
    public class LightOffCommand: ICommand
    {
        private readonly Light light;

        public LightOffCommand(Light light)
        {
            this.light = light;
        }

        public void Execute()
        {
            light.Off();
        }
    }
}

下边试五个略带挑衅性的, 音响:

namespace CommandPattern.Devices
{
    public class Stereo
    {
        public void On()
        {
            System.Console.WriteLine("Stereo is on.");
        }

        public void Off()
        {
            System.Console.WriteLine("Stereo is off.");
        }

        public void SetCD()
        {
            System.Console.WriteLine("Stereo is set for CD input.");
        }

        public void SetVolume(int volume)
        {
            System.Console.WriteLine($"Stereo's volume is set to {volume}");
        }
    }
}

动静展开命令:

using CommandPattern.Abstractions;

namespace CommandPattern.Devices
{
    public class StereoOnWithCDCommand : ICommand
    {
        private readonly Stereo stereo;

        public StereoOnWithCDCommand(Stereo stereo)
        {
            this.stereo = stereo;
        }

        public void Execute()
        {
            stereo.On();
            stereo.SetCD();
            stereo.SetVolume(10);
        }
    }
}

测量试验运转:

using System;
using CommandPattern.Commands;
using CommandPattern.Devices;
using CommandPattern.RemoteControls;

namespace CommandPattern
{
    class Program
    {
        static void Main(string[] args)
        {
            var remote = new RemoteControl();
            var light = new Light();
            var lightOn = new LightOnCommand(light);
            var lightOff = new LightOffCommand(light);
            var garageDoor = new GarageDoor();
            var garageDoorOpen = new GarageDoorOpenCommand(garageDoor);
            var garageDoorClose = new GarageDoorCloseCommand(garageDoor);
            var stereo = new Stereo();
            var stereoOnWithCD = new StereoOnWithCDCommand(stereo);
            var stereoOff = new StereoOffCommand(stereo);

            remote.SetCommand(0, lightOn, lightOff);
            remote.SetCommand(1, garageDoorOpen, garageDoorClose);
            remote.SetCommand(2, stereoOnWithCD, stereoOff);

            System.Console.WriteLine(remote);

            remote.OnButtonWasPressed(0);
            remote.OffButtonWasPressed(0);
            remote.OnButtonWasPressed(1);
            remote.OffButtonWasPressed(1);
            remote.OnButtonWasPressed(2);
            remote.OffButtonWasPressed(2);
        }
    }
}

澳门新萄京官方网站 10

该须要的宏图图:

澳门新萄京官方网站 11

再有一个难点...裁撤开关呢?

 

  分析5:命令情势能够将“动作的诉求者”从“动作的实行者”对象中解耦,在此个例子中,央求者能够是遥控器,而实践者对象正是厂商类在那之中之风流罗曼蒂克的实例。

贯彻打消按键

  1. 可以在ICommand接口里面增多多个undo()方法, 然后在此中施行上叁遍动作相反的动作就可以:

    namespace CommandPattern.Abstractions {

     public interface ICommand
     {
         void Execute();
         void Undo();
     }
    

    }

例如说开灯:

using CommandPattern.Abstractions;
using CommandPattern.Devices;

namespace CommandPattern.Commands
{
    public class LightOnCommand : ICommand
    {
        private readonly Light light;

        public LightOnCommand(Light light)
        {
            this.light = light;
        }

        public void Execute()
        {
            light.On();
        }

        public void Undo()
        {
            light.Off();
        }
    }
}

遥控器:

using System.Text;
using CommandPattern.Abstractions;
using CommandPattern.Commands;

namespace CommandPattern.RemoteControls
{
    public class RemoteControlWithUndo
    {
        private ICommand[] onCommands;
        private ICommand[] offCommands;
        private ICommand undoCommand;

        public RemoteControlWithUndo()
        {
            onCommands = new ICommand[7];
            offCommands = new ICommand[7];

            var noCommand = new NoCommand();
            for (int i = 0; i < 7; i  )
            {
                onCommands[i] = noCommand;
                offCommands[i] = noCommand;
            }
            undoCommand = noCommand;
        }

        public void SetCommand(int slot, ICommand onCommand, ICommand offCommand)
        {
            onCommands[slot] = onCommand;
            offCommands[slot] = offCommand;
        }

        public void OnButtonWasPressed(int slot)
        {            
            onCommands[slot].Execute();
            undoCommand = onCommands[slot];
        }

        public void OffButtonWasPressed(int slot)
        {
            offCommands[slot].Execute();
            undoCommand = offCommands[slot];
        }

        public void UndoButtonWasPressed()
        {
            undoCommand.Undo();
        }

        public override string ToString()
        {
            var sb = new StringBuilder("n------------Remote Control-----------n");
            for(int i =0; i< onCommands.Length; i  ){
                sb.Append($"[slot{i}] {onCommands[i].GetType()}t{offCommands[i].GetType()} n");
            }
            return sb.ToString();
        }
    }
}

测验一下:

using System;
using CommandPattern.Commands;
using CommandPattern.Devices;
using CommandPattern.RemoteControls;

namespace CommandPattern
{
    class Program
    {
        static void Main(string[] args)
        {
            var remote = new RemoteControl();
            var light = new Light();
            var lightOn = new LightOnCommand(light);
            var lightOff = new LightOffCommand(light);
            var stereo = new Stereo();
            var stereoOnWithCD = new StereoOnWithCDCommand(stereo);
            var stereoOff = new StereoOffCommand(stereo);

            remote.SetCommand(0, lightOn, lightOff);
            remote.SetCommand(1, stereoOnWithCD, stereoOff);

            System.Console.WriteLine(remote);

            remote.OnButtonWasPressed(0);
            remote.OffButtonWasPressed(0);
            remote.OnButtonWasPressed(1);
            remote.OffButtonWasPressed(1);
        }
    }
}

澳门新萄京官方网站 12

主干是OK的, 不过有一些符合规律, 音响的开关状态倒是裁撤了, 不过它的音量(也富含播放媒质, 可是那一个自家就不去落实了)并从未复苏.

上边就来管理一下以此难点.

修改Stereo:

namespace CommandPattern.Devices
{
    public class Stereo
    {

        public Stereo()
        {
            Volume = 5;
        }

        public void On()
        {
            System.Console.WriteLine("Stereo is on.");
        }

        public void Off()
        {
            System.Console.WriteLine("Stereo is off.");
        }

        public void SetCD()
        {
            System.Console.WriteLine("Stereo is set for CD input.");
        }

        private int volume;
        public int Volume
        {
            get { return volume; }
            set
            {
                volume = value;
                System.Console.WriteLine($"Stereo's volume is set to {volume}");
            }
        }

    }
}

命令:

using CommandPattern.Abstractions;

namespace CommandPattern.Devices
{
    public class StereoOnWithCDCommand : ICommand
    {
        private int previousVolume;

        private readonly Stereo stereo;
public StereoOnWithCDCommand(Stereo stereo)
        {
            this.stereo = stereo;
       previousVolume = stereo.Volume;
        }

        public void Execute()
        {
            stereo.On();
            stereo.SetCD();
            stereo.Volume = 10;
        }

        public void Undo()
        {
            stereo.Volume = previousVolume;
            stereo.SetCD();
            stereo.Off();
        }
    }
}

运行:

澳门新萄京官方网站 13

概念命令格局

  指令情势将“央浼”封装成对象,以便利用不一致的伸手、队列可能日志来参数化别的对象。

  一声令下方式也支撑可收回的操作。

  命令对象将动作和接纳者包进对象中。

  分析6:选择命令对象,把乞求(比方张开电灯卡塔尔国封装成八个特定对象(比如客厅电灯对象卡塔尔国。所以,若是对各样按键都存款和储蓄一个限令对象,那么当按键被按下的时候,就能够请命令对象做相关的劳作。遥控器并无需知道专门的学行业内部容是什么,只要有个指令对象能喝不利的对象关系,把事情做好就足以了。

急需改换----叁个按键调节多少个设备的八个动作

Party Mode (集会情势):

思路是成立风姿浪漫种命令, 它可以执行多少个别的命令

澳门新萄京官方网站命令格局,封装调用。MacroCommand:

using CommandPattern.Abstractions;

namespace CommandPattern.Commands
{
    public class MacroCommand : ICommand
    {
        private ICommand[] commands;

        public MacroCommand(ICommand[] commands)
        {
            this.commands = commands;
        }

        public void Execute()
        {
            for (int i = 0; i < commands.Length; i  )
            {
                commands[i].Execute();
            }
        }

        public void Undo()
        {
            for (int i = 0; i < commands.Length; i  )
            {
                commands[i].Undo();
            }
        }
    }
}

应用那个MacroCommand:

using System;
using CommandPattern.Abstractions;
using CommandPattern.Commands;
using CommandPattern.Devices;
using CommandPattern.RemoteControls;

namespace CommandPattern
{
    class Program
    {
        static void Main(string[] args)
        {
            var light = new Light();
            var lightOn = new LightOnCommand(light);
            var lightOff = new LightOffCommand(light);
            var garageDoor = new GarageDoor();
            var garageDoorOpen = new GarageDoorOpenCommand(garageDoor);
            var garageDoorClose = new GarageDoorCloseCommand(garageDoor);
            var stereo = new Stereo();
            var stereoOnWithCD = new StereoOnWithCDCommand(stereo);
            var stereoOff = new StereoOffCommand(stereo);

            var macroOnCommand = new MacroCommand(new ICommand[] { lightOn, garageDoorOpen, stereoOnWithCD });
            var macroOffCommand = new MacroCommand(new ICommand[] { lightOff, garageDoorClose, stereoOff });

            var remote = new RemoteControl();
            remote.SetCommand(0, macroOnCommand, macroOffCommand);
            System.Console.WriteLine(remote);

            System.Console.WriteLine("--- Pushing Macro on ---");
            remote.OnButtonWasPressed(0);
            System.Console.WriteLine("--- Pushing Macro off ---");
            remote.OffButtonWasPressed(0);
        }
    }
}

澳门新萄京官方网站 14

 

 

  分析7:运用那几个情势,我们能够创立一个API,将那些命令对象加载到开关插槽,让遥控器的代码尽量有限支撑轻易。而把家用电器自动化的劳作和进行该专门的学业的靶子一同封装在指令对象中。

一声令下格局其实采Nabi方

澳门新萄京官方网站命令格局,封装调用。指令方式的类图

 澳门新萄京官方网站 15

 

 

用命令方式落成遥控器难题的类图:

澳门新萄京官方网站 16 

 

二、详细表明

恳请队列

澳门新萄京官方网站 17

其风流洒脱职业行列是如此专业的: 你增多命令到行列的尾声, 在队列的另黄金年代端有多少个线程. 线程那样专门的学业: 它们从队列移除一个命令, 调用它的execute()方法, 然后等待调用甘休, 然后废弃这几个命令再赢得叁个新的命令.

如此大家就足以把总计量节制到一定的线程数上边了. 职业行列和做专门的学问的靶子也是解耦的.

废除操作的得以达成

  在Command接口中步入undo()方法,然后每一个具体的命令类都落到实处那个格局:undo方法中调用的操作和execute()方法中的操作相反,举个例子on的反面是off。

  遥控器类也要做一些校订:到场新的实例变量记录上贰个操作,当按下撤消按键,就调用该实例变量的undo()方法。

  要是撤废到某三个景色须求记录一些变量值,则在execute()方法中加入保存操作前状态数值的语句,然后在undo()的时候恢复生机。

  后生可畏经想要数十次注销,即废除到很早从前的情事,能够采取四个储藏室记录操作进度的每三个下令。

  命令情势:将呼吁封装成对象,那能够令你利用区别的乞请、队列,或许日志必要来参数化别的对象。命令方式也能够支撑废除操作。

笔录央浼

澳门新萄京官方网站 18

澳门新萄京官方网站 19

以那一件事例正是采纳命令形式记录央求动作的野史, 如若出难题了, 可以遵守那些历史实行恢复生机.

 

 

  以后留意看这一个概念,我们知道三个限令对象通过在特定接受者上绑定少年老成组动作来封装叁个伸手。要实现那一点,命令对象将动作和选取者包进对象中。那一个目的只暴露出三个execute()方法,当此方法被调用的时候,选拔者就能进展这一个动作。从外侧来看,其余对象不领会毕竟哪个选择者进行了怎么着动作,只知道若是调用execute()方法,央浼的目标就能达成。

其它

其大器晚成种类的代码小编放在那了: 

 

宏命令

  通过贰个键,调整两种操作。

  在宏命令中,用命令数组存款和储蓄一大堆命令,当以此宏命令被遥控器试行时,就叁遍性实行数组里的各样命令。

1.概念命令情势类图:

 

 澳门新萄京官方网站 20

指令形式的愈来愈多用项

 

队列哀告

  命令能够将运算块打包(三个接纳者和生龙活虎组动作卡塔 尔(阿拉伯语:قطر‎,然后将它传来传去,有如对平日的靶子同样。

  大家得以利用那样的特色衍生一些行使,比如:日程布署,线程池,工作行列等。

  想象有三个行事行列:你在后生可畏端增添命令,然后另风华正茂端则是线程。

  线程从队列中收取命令,调用它的execute()方法,等待这些调用实现,然后将此命令对象抛弃,在抽出下二个下令……

 

日志央浼

  有个别应用需求大家将富有的动作都记录在日记中,并能在系统死机之后,重新调用这么些动作复苏到事先的事态。

  通过新添多个主意store()、load(),命令情势就能够协助那或多或少。

  在Java中,大家得以应用目的的种类化(塞里alization卡塔尔达成那个方法,不过常常感到系列化最佳依然只用在目的的悠久化上(persistence卡塔尔。

  如何是好:当大家试行命令的时候,将历史记录积存在磁盘中。生龙活虎旦系统死机,大家就能够将下令对象重新加载,并成批地依次调用这几个指标的execute()方法。

 

题外话:《Head First设计格局》读书笔记类别的更新暂停,笔者不会报告您是因为体育场合的书超期何况被人约定了所以本身借不到了。年后开课再说吧,希望自个儿能坚持不懈。

 

2.底下的类图提供了布署的全貌:

 澳门新萄京官方网站 21

 

问:如果具备了三个遥控器,却回天无力光凭按下多少个开关,就同一时候能弄暗灯的亮光、张开音响和TV、设置好mp3,并让空气能热水器领头加温,那么要那一个遥控器还犹怎么着意义?

答:那时候就能够用到命令格局的延长“宏命令”,创建风姿浪漫种新的通令,用来推行此外一群命令。在宏命令中,用命令数组(集结卡塔 尔(阿拉伯语:قطر‎存款和储蓄一大堆命令,当以此宏命令被遥控器施行时,就一回性推行数组里的各个命令。(具体内容,可在代码列表查看卡塔 尔(阿拉伯语:قطر‎

 

问:收信人一定有必不可缺存在呢?为啥命令对象不直接达成execute()方法的内幕。

答:相近的话,大家尽量设计“傻瓜”命令对象,它只略知风姿洒脱二调用多少个选择者的三个行事。不过,有过多“聪明”命令对象会促成广大逻辑,直接完毕叁个呼吁。当然你能够设计聪明的授命对象,只是那样一来,调用者和选用者之间的解耦程度是比不上“白痴”命令对象的,况兼,你也不能把接纳者当做参数字传送给命令。

 

问:自己可以创立PartyCommand,然后在它的execute()方法中调用别的的一声令下,利用这种做法达成Party形式(Party Mode卡塔尔国吗?

答:您能够那样做。然后,那等于把Party方式“硬编码”到PartyCommand中。为啥要这么劳累呢?利用宏命令,你能够动态地决定PartyCommand是由哪些命令组成,所以宏命令在利用上越来越灵活。常常的话,宏命令的做法更文雅,也必要少之又少的新代码。

 

问:本身如何能够贯彻多档案的次序的吊销操作?换句话说,作者希望能够按下撤消按键许多次,打消往很早很早从前的状态。

答:其实这一定轻易做到,不要只记录最终一个被实践的吩咐,而选取多个库房记录操作进程的每一个命令。然后,不管如什么时候候按下了撤回按键,你都得以从旅舍中抽取最上层的命令,然后调用它的Undo()方法。

 

3.指令格局的越来越多用处:

  (1)队列乞求:命令能够将运算块打包(多个选取者和黄金年代组动作卡塔 尔(阿拉伯语:قطر‎,然后将它传来传去,就好像日常的靶子同样。它竟然能够在不一样的线程中被调用。我们得以选用那样的特性衍生一些用到,比方:日程安顿、线程池、专业行列等。

想像有叁个干活行列,你在某一端增添命令,然后另风姿洒脱端则是线程,线程举办上边包车型大巴动作,从队列中抽取多少个指令,调用它的Execute()方法,等待这一个调用达成,然后将此命令对象甩掉,再抽出下三个命令......

  (2)日记哀告:某个应用必要大家将装有的动作都记录在日记中,并能在系统死机之后,重新调用那么些动作苏醒到事先的景观。通过新添多少个措施(Store()、Load()卡塔 尔(阿拉伯语:قطر‎,命令情势能够扶助这点。这种日志的主意对于遥控器来讲没风趣,不过,有无数调用大型数据结构的动作的应用,不恐怕在历次更动发生时被急迅地囤积。通过利用记录日志,大家得以将上次检查点之后的享有操作记录下来,假如系统出现境况,从检查点初步采用那几个操作。

举例说,对于石英表格应用,大家兴许想要完成的失实恢复生机措施是将电子钟格的操作记录在日记中,并不是历次原子钟格黄金年代有浮动就记录整个电子手表格。对更加尖端的应用来讲,这么些本事能够被扩大应用到事务管理中,也正是说,一整组操作必需产生后才算灵光。

 

4.总结:

(1卡塔尔国当须求将发出央浼的对象和推行央浼的指标解耦的时候,使用命令形式

(2卡塔尔国在被解耦的两个之间是经过命令对象开展关联的,命令对象封装了收信人和几个或风姿罗曼蒂克组动作。

(3卡塔尔调用者通过调用命令对象的execute()发出乞请,那会使得选用者的动作被调用。

(4卡塔 尔(英语:State of Qatar)调用者能够接收命令当做参数,甚至在运营时动态地举办。

(5卡塔 尔(阿拉伯语:قطر‎命令能够支撑废除,做法是完成一个Undo()方法来回到execute()被奉行前的景况。

(6卡塔尔国宏命令是命令的豆蔻梢头种简易的延伸,允许调用三个指令,宏方法也足以扶持撤销。

(7卡塔 尔(阿拉伯语:قطر‎命令也能够用来完毕日志和工作系统。

三、代码列表

澳门新萄京官方网站 22澳门新萄京官方网站 23

/// <summary>
/// 命令接口
/// </summary>
public interface ICommand
{
    /// <summary>
    /// 执行
    /// </summary>
    void Execute();
    /// <summary>
    /// 撤销
    /// </summary>
    void Undo();
}
public class RemoteControl
{
    private ICommand[] onCommands;
    private ICommand[] offCommands;
    private ICommand undoCommand;

    public RemoteControl()
    {
        onCommands = new ICommand[7];
        offCommands = new ICommand[7];
        ICommand noCommand = new NoCommand();
        for (int i = 0; i < 7; i  )
        {
            onCommands[i] = noCommand;
            offCommands[i] = noCommand;
        }
        undoCommand = noCommand;
    }

    public void SetCommand(int slot, ICommand onCommand, ICommand offCommand)
    {
        onCommands[slot] = onCommand;
        offCommands[slot] = offCommand;
    }

    public void OnButtonWasPushed(int slot)
    {
        onCommands[slot].Execute();
        undoCommand = onCommands[slot];
    }

    public void OffButtonWasPushed(int slot)
    {
        offCommands[slot].Execute();
        undoCommand = offCommands[slot];
    }

    public void UndoButtonWasPushed()
    {
        undoCommand.Undo();
    }

    public override string ToString()
    {
        StringBuilder sb=new StringBuilder();
        sb.Append("n---------Remote Control----------n");
        for (int i = 0; i < onCommands.Length; i  )
        {
            sb.AppendFormat("[slot {0}] {1}    {2}",i,onCommands[i].GetType().FullName, offCommands[i].GetType().FullName);
            sb.AppendLine();
        }
        return sb.ToString();
    }
}
public class SimpleRemoteControl
{
    private ICommand slot;

    public void SetCommand(ICommand command)
    {
        slot = command;
    }

    public void ButtonWasPressed()
    {
        slot.Execute();
    }
}
//Worker
/// <summary>
/// 吊扇
/// </summary>
public class CeilLingFan
{
    public CeilLingFanSpeed speed { get; private set; } = 0;
    private string name;

    public CeilLingFan(string name)
    {
        this.name = name;
    }

    /// <summary>
    /// 高速
    /// </summary>
    public void High()
    {
        speed = CeilLingFanSpeed.High;
        Console.WriteLine("{0} ceilLingFan is highs", name);
    }
    /// <summary>
    /// 中速
    /// </summary>
    public void Medium()
    {
        speed = CeilLingFanSpeed.Medium;
        Console.WriteLine("{0} ceilLingFan is medium", name);
    }
    /// <summary>
    /// 低速
    /// </summary>
    public void Low()
    {
        speed = CeilLingFanSpeed.Low;
        Console.WriteLine("{0} ceilLingFan is low", name);
    }
    /// <summary>
    /// 关闭
    /// </summary>
    public void Off()
    {
        speed = CeilLingFanSpeed.Off;
        Console.WriteLine("{0} ceilLingFan is Off", name);
    }

    public enum CeilLingFanSpeed { High = 3, Medium = 2, Low = 1, Off = 0 }
}
/// <summary>
/// 车库门
/// </summary>
public class GarageDoor
{
    private string name;

    public GarageDoor(string name)
    {
        this.name = name;
    }

    /// <summary>
    /// 上升
    /// </summary>
    public void Up()
    {
        Console.WriteLine("{0} Garage door is open", name);
    }
    /// <summary>
    /// 下降
    /// </summary>
    public void Down()
    {
        Console.WriteLine("{0} Garage door is close", name);
    }
    /// <summary>
    /// 停止
    /// </summary>
    public void Stop()
    {
        Console.WriteLine("{0} Garage door is stop", name);
    }
    /// <summary>
    /// 灯光开启
    /// </summary>
    public void LightOn()
    {
        Console.WriteLine("{0} Garage Light is on", name);
    }
    /// <summary>
    /// 灯光关闭
    /// </summary>
    public void LightOff()
    {
        Console.WriteLine("{0} Garage Light is off", name);
    }
}
/// <summary>
/// 热浴盆
/// </summary>
public class Hottub
{
    /// <summary>
    /// 水循环
    /// </summary>
    public void Circulata()
    {
        Console.WriteLine("Tub water is circulata");
    }
    /// <summary>
    /// 喷射打开
    /// </summary>
    public void JetsOn()
    {
        Console.WriteLine("Jets is on");
    }
    /// <summary>
    /// 喷射关闭
    /// </summary>
    public void JetsOff()
    {
        Console.WriteLine("Jets is Off");
    }
    /// <summary>
    /// 设置温度
    /// </summary>
    public void SetTemperature()
    {
        Console.WriteLine("Default temperature is 46°C");
    }
}
/// <summary>
/// 灯光
/// </summary>
public class Light
{
    private string name;

    public Light(string name)
    {
        this.name = name;
    }

    /// <summary>
    /// 开启
    /// </summary>
    public void On()
    {
        Console.WriteLine("{0} light is On", name);
    }
    /// <summary>
    /// 关闭
    /// </summary>
    public void Off()
    {
        Console.WriteLine("{0} light is Off", name);
    }
}
/// <summary>
/// 立体声
/// </summary>
public class Stereo
{
    private string name;

    public Stereo(string name)
    {
        this.name = name;
    }

    /// <summary>
    /// 开启
    /// </summary>
    public void On()
    {
        Console.WriteLine("{0} Stereo is on", name);
    }
    /// <summary>
    /// 关闭
    /// </summary>
    public void Off()
    {
        Console.WriteLine("{0} Stereo is off", name);
    }
    /// <summary>
    /// 设置CD
    /// </summary>
    public void SetCd()
    {
        Console.WriteLine("Stereo Cd is on");
    }
    /// <summary>
    /// 设置DVD
    /// </summary>
    public void SetDvd()
    {
        Console.WriteLine("Stereo Dvd is on");
    }
    /// <summary>
    /// 设置收音机
    /// </summary>
    public void SetRadio()
    {
        Console.WriteLine("Stereo radio is on");
    }
    /// <summary>
    /// 设置音量
    /// </summary>
    public void SetVolume(byte volume)
    {
        Console.WriteLine("Stereo volume is {0}", volume);
    }
}
/// <summary>
/// 电视
/// </summary>
public class TV
{
    private string name;

    public TV(string name)
    {
        this.name = name;
    }

    /// <summary>
    /// 开启
    /// </summary>
    public void On()
    {
        Console.WriteLine("{0} TV is on", name);
    }
    /// <summary>
    /// 关闭
    /// </summary>
    public void Off()
    {
        Console.WriteLine("{0} TV is off", name);
    }
    /// <summary>
    /// 设置频道
    /// </summary>
    public void SetInputChannel()
    {
        Console.WriteLine("Defualt channel is CCTV1");
    }
    /// <summary>
    /// 设置音量
    /// </summary>
    public void SetVolume()
    {
        Console.WriteLine("Defualt volume is 5");
    }
}
//Commands
/// <summary>
/// 吊扇基础命令类
/// </summary>
public abstract class CeilingFanCommand : ICommand
{
    protected CeilLingFan ceilLingFan;
    private CeilLingFan.CeilLingFanSpeed speed;

    public void Execute()
    {
        speed = ceilLingFan.speed;
        FanExecute();
    }

    public abstract void FanExecute();

    public void Undo()
    {
        switch (speed)
        {
            case CeilLingFan.CeilLingFanSpeed.High:
                ceilLingFan.High();
                break;
            case CeilLingFan.CeilLingFanSpeed.Medium:
                ceilLingFan.Medium();
                break;
            case CeilLingFan.CeilLingFanSpeed.Low:
                ceilLingFan.Low();
                break;
            case CeilLingFan.CeilLingFanSpeed.Off:
                ceilLingFan.Off();
                break;
        }
    }
}
public class CeilLingFanHighCommand : CeilingFanCommand
{
    public CeilLingFanHighCommand(CeilLingFan ceilLingFan)
    {
        base.ceilLingFan = ceilLingFan;
    }

    public override void FanExecute()
    {
        ceilLingFan.High();
    }
}
public class CeilLingFanLowCommand : CeilingFanCommand
{
    public CeilLingFanLowCommand(CeilLingFan ceilLingFan)
    {
        base.ceilLingFan = ceilLingFan;
    }

    public override void FanExecute()
    {
        ceilLingFan.Low();
    }
}
public class CeilLingFanMediumCommand : CeilingFanCommand
{
    public CeilLingFanMediumCommand(CeilLingFan ceilLingFan)
    {
        base.ceilLingFan = ceilLingFan;
    }

    public override void FanExecute()
    {
        ceilLingFan.Medium();
    }
}
public class CeilLingFanOffCommand : CeilingFanCommand
{
    public CeilLingFanOffCommand(CeilLingFan ceilLingFan)
    {
        base.ceilLingFan = ceilLingFan;
    }

    public override void FanExecute()
    {
        ceilLingFan.Off();
    }
}
public class GarageDoorCloseCommand : ICommand
{
    private GarageDoor garageDoor;

    public GarageDoorCloseCommand(GarageDoor garageDoor)
    {
        this.garageDoor = garageDoor;
    }

    public void Execute()
    {
        garageDoor.Down();
        garageDoor.LightOff();
    }

    public void Undo()
    {
        garageDoor.LightOn();
        garageDoor.Up();
    }
}
public class GarageDoorOpenCommand : ICommand
{
    private GarageDoor garageDoor;

    public GarageDoorOpenCommand(GarageDoor garageDoor)
    {
        this.garageDoor = garageDoor;
    }

    public void Execute()
    {
        garageDoor.Up();
        garageDoor.LightOn();
    }

    public void Undo()
    {
        garageDoor.Down();
        garageDoor.LightOff();
    }
}
public class HottubOffCommand:ICommand
{
    private Hottub hottub;

    public HottubOffCommand(Hottub hottub)
    {
        this.hottub = hottub;
    }

    public void Execute()
    {
        hottub.JetsOff();
    }

    public void Undo()
    {
        hottub.JetsOn();
    }
}
public class HottubOnCommand : ICommand
{
    private Hottub hottub;

    public HottubOnCommand(Hottub hottub)
    {
        this.hottub = hottub;
    }

    public void Execute()
    {
        hottub.JetsOn();
        hottub.SetTemperature();
    }

    public void Undo()
    {
        hottub.JetsOff();
    }
}
public class LightOffCommand:ICommand
{
    private Light light;

    public LightOffCommand(Light light)
    {
        this.light = light;
    }

    public void Execute()
    {
        light.Off();
    }

    public void Undo()
    {
        light.On();
    }
}
public class LightOnCommand : ICommand
{
    private Light light;

    public LightOnCommand(Light light)
    {
        this.light = light;
    }

    public void Execute()
    {
        light.On();
    }

    public void Undo()
    {
        light.Off();
    }
}
/// <summary>
/// 更多命令(宏命令)
/// </summary>
public class MacroCommand:ICommand
{
    private ICommand[] commands;

    public MacroCommand(ICommand[] commands)
    {
        this.commands = commands;
    }

    public void Execute()
    {
        foreach (ICommand command in commands)
        {
            command.Execute();
        }
    }

    public void Undo()
    {
        foreach (ICommand command in commands)
        {
            command.Undo();
        }
    }
}
/// <summary>
/// 没有命令
/// </summary>
public class NoCommand : ICommand
{
    public void Execute()
    {

    }

    public void Undo()
    {

    }
}
public class StereoOffCommand : ICommand
{
    private Stereo stereo;

    public StereoOffCommand(Stereo stereo)
    {
        this.stereo = stereo;
    }

    public void Execute()
    {
        stereo.Off();
    }

    public void Undo()
    {
        stereo.On();
    }
}
public class StereoOnCommand : ICommand
{
    private Stereo stereo;

    public StereoOnCommand(Stereo stereo)
    {
        this.stereo = stereo;
    }

    public void Execute()
    {
        stereo.On();
    }

    public void Undo()
    {
        stereo.Off();
    }
}
public class StereoOnWithCDCommand:ICommand
{
    private Stereo stereo;

    public StereoOnWithCDCommand(Stereo stereo)
    {
        this.stereo = stereo;
    }

    public void Execute()
    {
        stereo.On();
        stereo.SetCd();
        stereo.SetVolume(11);
    }

    public void Undo()
    {
        stereo.Off();
    }
}
public class TVOffCommand:ICommand
{
    private TV tv;

    public TVOffCommand(TV tv)
    {
        this.tv = tv;
    }

    public void Execute()
    {
        tv.Off();
    }

    public void Undo()
    {
        tv.On();
    }
}
public class TVOnCommand : ICommand
{
    private TV tv;

    public TVOnCommand(TV tv)
    {
        this.tv = tv;
    }

    public void Execute()
    {
        tv.On();
        tv.SetInputChannel();
        tv.SetVolume();
    }

    public void Undo()
    {
        tv.Off();
    }
}
//RunTest
[Test]
public void RemoteLoader()
{
    //单个插槽的简单控制装置
    /*SimpleRemoteControl remote = new SimpleRemoteControl();
    Light light = new Light();
    GarageDoor garageDoor = new GarageDoor();
    LightOnCommand lightOn = new LightOnCommand(light);
    GarageDoorOpenCommand garageOpen = new GarageDoorOpenCommand(garageDoor);
    remote.SetCommand(lightOn);
    remote.ButtonWasPressed();
    remote.SetCommand(garageOpen);
    remote.ButtonWasPressed();*/

    //多个插槽(含有关闭功能)的控制装置
    /*RemoteControl remoteControl = new RemoteControl();
    Light livingRoomLight = new Light("Living Room");
    Light kitchenLight = new Light("Kitchen");
    CeilLingFan ceilLingFan = new CeilLingFan("Living Room");
    GarageDoor garageDoor = new GarageDoor("");
    Stereo stereo = new Stereo("Living Room");

    LightOnCommand livingRoomLightOn = new LightOnCommand(livingRoomLight);
    LightOffCommand livingRoomLightOff = new LightOffCommand(livingRoomLight);
    LightOnCommand kitchenLightOn = new LightOnCommand(kitchenLight);
    LightOffCommand kitchenLightOff = new LightOffCommand(kitchenLight);
    CeilLingFanLowCommand ceilingFanLow = new CeilLingFanLowCommand(ceilLingFan);
    CeilLingFanOffCommand ceilLingFanOff = new CeilLingFanOffCommand(ceilLingFan);
    GarageDoorOpenCommand garageDoorOpen = new GarageDoorOpenCommand(garageDoor);
    GarageDoorCloseCommand garageDoorClose = new GarageDoorCloseCommand(garageDoor);
    StereoOnWithCDCommand stereoOnWithCd = new StereoOnWithCDCommand(stereo);
    StereoOffCommand stereoOff = new StereoOffCommand(stereo);

    remoteControl.SetCommand(0, livingRoomLightOn, livingRoomLightOff);
    remoteControl.SetCommand(1, kitchenLightOn, kitchenLightOff);
    remoteControl.SetCommand(2, ceilingFanLow, ceilLingFanOff);
    remoteControl.SetCommand(3, garageDoorOpen, garageDoorClose);
    remoteControl.SetCommand(4, stereoOnWithCd, stereoOff);

    Console.WriteLine(remoteControl);

    remoteControl.OnButtonWasPushed(0);
    remoteControl.OffButtonWasPushed(0);
    remoteControl.OnButtonWasPushed(1);
    remoteControl.OffButtonWasPushed(1);
    remoteControl.OnButtonWasPushed(2);
    remoteControl.OffButtonWasPushed(2);
    remoteControl.OnButtonWasPushed(3);
    remoteControl.OffButtonWasPushed(3);
    remoteControl.OnButtonWasPushed(4);
    remoteControl.OffButtonWasPushed(4);*/

    //多个插槽(含有关闭功能,含有撤销功能)的控制装置
    /*RemoteControl remoteControl = new RemoteControl();
    Light livingRoomLight = new Light("Living Room");
    LightOnCommand livingRoomLightOn = new LightOnCommand(livingRoomLight);
    LightOffCommand livingRoomLightOff = new LightOffCommand(livingRoomLight);
    remoteControl.SetCommand(0, livingRoomLightOn, livingRoomLightOff);

    remoteControl.OnButtonWasPushed(0);
    remoteControl.OffButtonWasPushed(0);
    Console.WriteLine(remoteControl);
    remoteControl.UndoButtonWasPushed();
    remoteControl.OffButtonWasPushed(0);
    remoteControl.OnButtonWasPushed(0);
    Console.WriteLine(remoteControl);
    remoteControl.UndoButtonWasPushed();*/

    //多个插槽(含有状态对象的撤销功能)的控制装置
    /*RemoteControl remoteControl = new RemoteControl();
    CeilLingFan ceilLingFan = new CeilLingFan("Living Room");
    CeilLingFanHighCommand ceilingFanHigh = new CeilLingFanHighCommand(ceilLingFan);
    CeilLingFanMediumCommand ceilLingFanMedium = new CeilLingFanMediumCommand(ceilLingFan);
    CeilLingFanOffCommand ceilLingFanOff = new CeilLingFanOffCommand(ceilLingFan);

    remoteControl.SetCommand(0, ceilLingFanMedium, ceilLingFanOff);
    remoteControl.SetCommand(1, ceilingFanHigh, ceilLingFanOff);

    remoteControl.OnButtonWasPushed(0);
    remoteControl.OffButtonWasPushed(0);
    Console.WriteLine(remoteControl);
    remoteControl.UndoButtonWasPushed();

    remoteControl.OnButtonWasPushed(1);
    Console.WriteLine(remoteControl);
    remoteControl.UndoButtonWasPushed();*/

    //多个插槽(含有宏命令)的控制装置
    RemoteControl remoteControl = new RemoteControl();
    Light light = new Light("Living Room");
    TV tv = new TV("Living Room");
    Stereo stereo = new Stereo("Living Room");
    Hottub hottub = new Hottub();

    LightOnCommand lightOn = new LightOnCommand(light);
    StereoOnCommand stereoOn = new StereoOnCommand(stereo);
    TVOnCommand tvOn = new TVOnCommand(tv);
    HottubOnCommand hottubOn = new HottubOnCommand(hottub);

    LightOffCommand lightOff = new LightOffCommand(light);
    StereoOffCommand stereoOff = new StereoOffCommand(stereo);
    TVOffCommand tvOff = new TVOffCommand(tv);
    HottubOffCommand hottubOff = new HottubOffCommand(hottub);

    ICommand[] partyOn = { lightOn, stereoOn, tvOn, hottubOn };
    ICommand[] partyOff = { lightOff, stereoOff, tvOff, hottubOff };
    MacroCommand partyOnMacro = new MacroCommand(partyOn);
    MacroCommand partyOffMacro = new MacroCommand(partyOff);
    remoteControl.SetCommand(0, partyOnMacro, partyOffMacro);

    Console.WriteLine(remoteControl);
    Console.WriteLine("-----Pushing Macro On-----");
    remoteControl.OnButtonWasPushed(0);
    Console.WriteLine("=====Pushing Macro Off----");
    remoteControl.OffButtonWasPushed(0);
}

View Code

---------------------------------以上内容听新闻说《head frist design mode》举办收拾

本文由澳门新萄京官方网站发布于www.8455.com,转载请注明出处:澳门新萄京官方网站命令格局,封装调用

关键词: