命令模式

来源:http://www.cnblogs.com/zwt-blog/archive/2017/04/23/6752800.html
-Advertisement-
Play Games

一、 基本概述 問題:假設有一個控制器,該控制器上有7個可編程的插槽,每個都可以指定到一個不同的家電裝置,每個插槽都有對應的開關按鈕。這個遙控器還具備一個整體的撤銷按鈕。廠家已經提供了控制家電基本處理類。希望你能夠創建一組控制遙控器的API,讓每個插槽都能夠控制一個或一組裝置。(如下圖,廠商類) 分 ...


一、   基本概述

  問題:假設有一個控制器,該控制器上有7個可編程的插槽,每個都可以指定到一個不同的家電裝置,每個插槽都有對應的開關按鈕。這個遙控器還具備一個整體的撤銷按鈕。廠家已經提供了控制家電基本處理類。希望你能夠創建一組控制遙控器的API,讓每個插槽都能夠控制一個或一組裝置。(如下圖,廠商類)

 

  分析1:廠家提供的類,有許多都具備On()和off()方法,除此之外還有一些其他的五花八門的方法。

  分析2:還不只這樣,聽起來似乎將來還會有更多的廠商類,而且每個類還會有各式各樣的方法。

  分析3:遙控器應該知道如何解讀按鈕被按下的動作,然後發出正確的請求,但是遙控器不需知道這些家電自動化的細節。

  分析4:我們不想讓遙控器包含一大堆if語句,例如“if slot1==Light,then light.On(),else if slot1==Hottub,then hottub.JetsOn()”.大家都知道這樣的設計很糟糕。且只要有新的廠商類進來,就必須修改現有的代碼,造成潛在的錯誤。

  分析5:命令模式可以將“動作的請求者”從“動作的執行者”對象中解耦,在這個例子中,請求者可以是遙控器,而執行者對象就是廠商類其中之一的實例。

  分析6:利用命令對象,把請求(例如打開電燈)封裝成一個特定對象(例如客廳電燈對象)。所以,如果對每個按鈕都存儲一個命令對象,那麼當按鈕被按下的時候,就可以請命令對象做相關的工作。遙控器並不需要知道工作內容是什麼,只要有個命令對象能喝正確的對象溝通,把事情做好就可以了。

  分析7:使用這個模式,我們能夠創建一個API,將這些命令對象載入到按鈕插槽,讓遙控器的代碼儘量保持簡單。而把家電自動化的工作和進行該工作的對象一起封裝在命令對象中。

二、詳細說明

  命令模式:將請求封裝成對象,這可以讓你使用不同的請求、隊列,或者日誌請求來參數化其他對象。命令模式也可以支持撤銷操作。

  現在仔細看這個定義,我們知道一個命令對象通過在特定接收者上綁定一組動作來封裝一個請求。要達到這一點,命令對象將動作和接收者包進對象中。這個對象只暴露出一個execute()方法,當此方法被調用的時候,接收者就會進行這些動作。從外面來看,其他對象不知道究竟哪個接收者進行了哪些動作,只知道如果調用execute()方法,請求的目的就能達到。

1.定義命令模式類圖:

 

2.下麵的類圖提供了設計的全貌:

 

 

問:如果擁有了一個遙控器,卻無法光憑按下一個按鈕,就同時能弄暗燈光、打開音響和電視、設置好DVD,並讓熱水器開始加溫,那麼要這個遙控器還有什麼意義?

答:此時就可以用到命令模式的延伸“巨集命令”,製造一種新的命令,用來執行其他一堆命令。在巨集命令中,用命令數組(集合)存儲一大堆命令,當這個巨集命令被遙控器執行時,就一次性執行數組裡的每個命令。(具體內容,可在代碼列表查看)

 

問:接收者一定有必要存在嗎?為何命令對象不直接實現execute()方法的細節。

答:一般來說,我們儘量設計“傻瓜”命令對象,它只懂得調用一個接收者的一個行為。然而,有許多“聰明”命令對象會實現許多邏輯,直接完成一個請求。當然你可以設計聰明的命令對象,只是這樣一來,調用者和接收者之間的解耦程度是比不上“傻瓜”命令對象的,而且,你也不能夠把接收者當做參數傳給命令。

 

問:我可以創建PartyCommand,然後在它的execute()方法中調用其他的命令,利用這種做法實現Party模式(Party Mode)嗎?

答:你可以這麼做。然後,這等於把Party模式“硬編碼”到PartyCommand中。為什麼要這麼麻煩呢?利用巨集命令,你可以動態地決定PartyCommand是由哪些命令組成,所以巨集命令在使用上更靈活。一般來說,巨集命令的做法更優雅,也需要較少的新代碼。

 

問:我如何能夠實現多層次的撤銷操作?換句話說,我希望能夠按下撤銷按鈕許多次,撤銷到很早很早以前的狀態。

答:其實這相當容易做到,不要只記錄最後一個被執行的命令,而使用一個堆棧記錄操作過程的每一個命令。然後,不管什麼時候按下了撤銷按鈕,你都可以從堆棧中取出最上層的命令,然後調用它的Undo()方法。

 

3.命令模式的更多用途:

  (1)隊列請求:命令可以將運算塊打包(一個接收者和一組動作),然後將它傳來傳去,就像是一般的對象一樣。它甚至可以在不同的線程中被調用。我們可以利用這樣的特性衍生一些應用,例如:日程安排、線程池、工作隊列等。

想象有一個工作隊列,你在某一端添加命令,然後另一端則是線程,線程進行下麵的動作,從隊列中取出一個命令,調用它的Execute()方法,等待這個調用完成,然後將此命令對象丟棄,再取出下一個命令......

  (2)日誌請求:某些應用需要我們將所有的動作都記錄在日誌中,並能在系統死機之後,重新調用這些動作恢復到之前的狀態。通過新增兩個方法(Store()、Load()),命令模式能夠支持這一點。這種日誌的方式對於遙控器來說沒有意義,然而,有許多調用大型數據結構的動作的應用,無法在每次改變發生時被快速地存儲。通過使用記錄日誌,我們可以將上次檢查點之後的所有操作記錄下來,如果系統出現狀況,從檢查點開始應用這些操作。

比方說,對於電子錶格應用,我們可能想要實現的錯誤恢復方式是將電子錶格的操作記錄在日誌中,而不是每次電子錶格一有變化就記錄整個電子錶格。對更高級的應用而言,這些技巧可以被擴展應用到事務處理中,也就是說,一整組操作必須完成後才算有效。

 

4.總結:

(1)當需要將發出請求的對象和執行請求的對象解耦的時候,使用命令模式

(2)在被解耦的兩者之間是通過命令對象進行溝通的,命令對象封裝了接收者和一個或一組動作。

(3)調用者通過調用命令對象的execute()發出請求,這會使得接收者的動作被調用。

(4)調用者可以接受命令當做參數,甚至在運行時動態地進行。

(5)命令可以支持撤銷,做法是實現一個Undo()方法來回到execute()被執行前的狀態。

(6)巨集命令是命令的一種簡單的延伸,允許調用多個命令,巨集方法也可以支持撤銷。

(7)命令也可以用來實現日誌和事務系統。

三、代碼列表

/// <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》進行整理


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 讀完了這本書,收穫很多,對程式設計有了很多新的理解。將每章模式的大概要點做了些筆記以備查閱,一些設計模式書讀完也對其瞭解得不是很透徹,需要以後在實踐中來不斷地加深理解吧。讀書過程中用Java跟著實踐了些部分模式的代碼上傳到了 "https://github.com/wanghaoxi3000/des ...
  • 1、使用Eclipse 建立Maven項目(webapp OR quickstart) 2、配置Maven,如下: 3、建立啟動Application 4、編輯Controller 5、通過application.properties對項目進行配置 項目文件佈局如下: 啟動Application程式 ...
  • 現象: 同事負責的項目轉到我的頭上,整理服務過程中發現了隊列的積壓問題。 為了搞清楚積壓的嚴重程度, 對隊列任務數每分鐘進行一次採樣,生成一個走勢圖, 隊列積壓情況一目瞭然,非常嚴重。 分析: 聽了同事對系統的介紹,猜測是mongo性能影響了處理效率,於是針對mongo進行分析 1. 使用mongo ...
  • 1. 前言 2. 所謂習慣認知 3. 開門見山的萬金油 第1條:抽象類設計註重對象性,介面設計註重服務性 第2條:更近的抽象類,更遠的介面 第3條:子類間有關係時考慮用抽象類,沒有關係時一定要用介面 第4條:版本迭代中優先考慮使用抽象類而不是介面 4. 設計是個性的妥協 5. 參考資料 1. 前言 ...
  • 程式優化是用於消除程式中大量的if else這種判斷語句 ...
  • 歷時兩個多月的時間,終於把effective c++又複習了一遍,比較慢,看的是英文版,之前看的時候做過一些筆記,但不夠詳細,這次筆者是從頭到尾的翻譯了一遍,加了一些標題,先記錄到word裡面,然後發佈到博客園上。這麼做是為了方便查閱,複習C++,同時練習英文,希望這些帖子也能夠對大家有所幫助。 有 ...
  • 什麼是觀察者模式 舉個例子來簡單說明下這個模式:假如現在你在一家報社訂閱了報紙,每當有新的期刊,那麼他們就會把報紙送到你家,如果你什麼時候不想看這一期刊的時候,你就可以取消訂閱,那麼這時候他們就不會將報紙送到你家了。這其實就是利用了觀察者模式,先給出兩個基本概念:主題,就相當於被觀察的對象,這裡指的 ...
  • 每天一個設計模式 -9 裝飾者模式 一、現實 使用繼承不總能夠實現最有彈性和最好維護的設計。 利用組合和委托可以在運行時具有繼承行為的效果。 利用繼承設計子類的行為,是在編譯時靜態決定的,而且所有的子類都會繼承到相同的行為。 利用組合的做法擴展對象的行為,就可以在運行時動態地進行擴展。 二、認識裝飾 ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...