日韩久久久精品,亚洲精品久久久久久久久久久,亚洲欧美一区二区三区国产精品 ,一区二区福利

Head First設計模式六-----命令模式(Command P

系統 2253 0
http://blog.sina.com.cn/s/blog_5016113a01009rta.html
命令模式定義
??? 將“請求”封裝成對象,以便使用不同的請求、隊列或者日志來參數化其他對象。命令模式也支持可撤銷的操作
命令模式可以將“動作的請求者”和“動作的執行者”分隔開來(解耦)

例子:設計一個家電自動化遙控器的API。遙控器有七個插頭,可以連接不同的家電電器,每個插頭有對應的開關按鈕,用來控制電器的開關。這個遙控器還具備一個整體的撤銷按鈕。

解析:
當遙控器按下“開”按鈕時,直接調用家用電器的“開”方法。但是有很多家用電器,每種家用電器的“開”方法名稱也不一定相同,這意味著每一個插頭的“開”按鈕按下時,都要判斷是什么家用電器,然后再調用它的“開”方法。

使用命令模式:
封裝方法調用,把方法調用封裝成對象。把每種家用電器的 “開”方法和執行“開”方法的電器封裝成一個統一標準的對象,遙控器通過操作統一標準的對象,來操作家用電器,就可以忽略每種家用電器之間的差異。
UML圖(點擊看大圖)

UML圖解
Light為電燈類,LightOnCommand封裝了Light和Light的on()方法,它符合Command的標準。遙控器通過操作Command來操作家用電器,從而忽略多種家用電器之間的差異。
    //1.Command接口形式:
public interface Command {
    public void execute();
}
//2.LightOnCommand形式:
public class LightOnCommand implements Command {
    Light light;                //封裝方法執行者
    public LightOnCommand(Light light) {
        this.light = light;
    }
    public void execute() {
        light.on();            //封裝方法
    }
}
//3.SimpleRemoteControl遙控器形式如:
public class SimpleRemoteControl {
    Command slot;
    public SimpleRemoteControl() {}
    public void setCommand(Command command) {
        slot = command;
    }
    public void buttonWasPressed() {
        slot.execute();   //遙控器不知道方法執行者到底是誰,它操作統一家用標準Command對象。
    }
}
//4.實際動作方式:
SimpleRemoteControl remote = new SimpleRemoteControl();
Light light = new Light();
LightOnCommand lightOn = new LightOnCommand(light); //封裝電燈“開”方法的對象。
remote.setCommand(lightOn);                    //把統一標準對象放入遙控器
remote.buttonWasPressed();  
  
????????

為遙控器實現撤銷(undo)按鈕
例子:遙控天花板吊扇,風扇有風速檔位(low、medium、hight),并且要實現撤銷按鈕,即打開風扇,撤銷后就關閉風扇,讓風扇回到打開前狀態。
UML圖

UML圖解
    1.CeilingFan為天花板風扇類,包含開關、調檔等方式
public class CeilingFan {
    public static final int HIGH = 3;        //風速檔位為3檔
    public static final int MEDIUM = 2;
    public static final int LOW = 1;
    public static final int OFF = 0;
    String location;                    //天花板的位置
    int speed;                        //當前風速檔位
    public CeilingFan(String location) {
        this.location = location;
        speed = OFF;
    }
    public void high() {
        speed = HIGH;
    }
    public void medium() {
        speed = MEDIUM;
    }
    public void low() {
        speed = LOW;
    }
    public void off() {
        speed = OFF;
    }
    public int getSpeed() {
        return speed;
    }
}
2.Command接口,家用電器執行/撤銷動作標準
public interface Command {
    public void execute();        //執行某個動作
    public void undo();        //撤銷execute()要執行的動作
}
3.CeilingFanHighCommand類,包含風扇調為最高檔位,和撤銷到原來狀態的方法
public class CeilingFanHighCommand implements Command {
    CeilingFan ceilingFan;
    int prevSpeed;                    //當前風速
    public CeilingFanHighCommand(CeilingFan ceilingFan) {
        this.ceilingFan = ceilingFan;
    }
    public void execute() {
        prevSpeed = ceilingFan.getSpeed();    //調為最高風速前,記下當時的風速,用于撤銷動作
        ceilingFan.high();
    }
    public void undo() {                //撤銷動作
        if (prevSpeed == CeilingFan.HIGH) {   
            //如果先前是最高風速,撤銷當前的動作,把風速調到最高。
            ceilingFan.high();
        } else if (prevSpeed == CeilingFan.MEDIUM) {
            ceilingFan.medium();
        } else if (prevSpeed == CeilingFan.LOW) {
            ceilingFan.low();
        } else if (prevSpeed == CeilingFan.OFF) {
            ceilingFan.off();
        }
    }
}
4.RemoteControlWithUndo為遙控器類
public class RemoteControlWithUndo {
    Command[] onCommands;        //封裝所有“開”命令,遙控器有7個開關
    Command[] offCommands;
    Command undoCommand;        //當前的命令
    public RemoteControlWithUndo() {
        onCommands = new Command[7];   
        //初始化7個開與關命令,命令為noCommand對象,它什么都不做
        offCommands = new Command[7];
        Command noCommand = new NoCommand();
        for(int i=0;i<7;i++) {
            onCommands[i] = noCommand;
            offCommands[i] = noCommand;
        }
        undoCommand = noCommand;
    }
    public void setCommand(int slot, Command onCommand, Command 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();
    }
 
}
  
實際動作方式:
RemoteControlWithUndo remoteControl = new RemoteControlWithUndo();
CeilingFan ceilingFan = new CeilingFan("Living Room");? //在客廳天花板上的吊扇
CeilingFanMediumCommand ceilingFanMedium = new CeilingFanMediumCommand(ceilingFan);??
//把風扇調到中檔,這是個“開”命令
CeilingFanOffCommand ceilingFanOff = new CeilingFanOffCommand(ceilingFan); //關閉風扇命令??????????
remoteControl.setCommand(0, ceilingFanMedium, ceilingFanOff);??????????
remoteControl.onButtonWasPushed(0);??????? //按下“開”
remoteControl.offButtonWasPushed(0);??????? //按下“關”
remoteControl.undoButtonWasPushed();??????? //按下 “撤銷”

NoCommand對象
NoCommand是一個空對象(null object),當你不想返回一個有意義的對象時,空對象就很有用??諏ο罂梢员苊馕覀冊诔绦蛑袑懮吓袛鄬ο笫欠駷榭盏膇f等語句。

Party模式
按下一個按鈕,就同時能打開音響、電燈、電視、設置好DVD,并讓熱水器開始加溫。
設計一個“宏”命令類
    public class MacroCommand implements Command {
    Command[] commands;                //使用命令數組存儲一大堆命令
    public MacroCommand(Command[] commands) {
        this.commands = commands;
    }
    public void execute() {    //這個宏命令被遙控器執行時,就一次性執行數組中的每一個命令
        for (int i = 0; i < commands.length; i++) {
            commands[i].execute();
        }
    }
    public void undo() { //撤銷宏命令,我認為應是:for (int i = commands.length-1; i >0; i--)
        for (int i = 0; i < commands.length; i++) {
            commands[i].undo();
        }
    }
}
  
實際動作方式
RemoteControl remoteControl = new RemoteControl();??
Command[] partyOn = {…………};??????? //一組“開”命令
Command[] partyOff = { ………...};??????? //一組“關”命令
MacroCommand partyOnMacro = new MacroCommand(partyOn);? //初始化宏命令
MacroCommand partyOffMacro = new MacroCommand(partyOff);
remoteControl.setCommand(0, partyOnMacro, partyOffMacro);
remoteControl.onButtonWasPushed(0);??????? //執行一組“開”命令
remoteControl.offButtonWasPushed(0);

如何學現多層次的撤銷操作?
使用一個堆棧記錄操作過程的每一個命令,按撤銷時從堆棧(后進先出)中取出最上層的命令,調用它的undo方法。
命令模式的更多用途
1.隊列請求
把一組命令放到隊列(先進先出)中,線程從隊列中一個一個刪除命令,然后調用它的excecute()方法。
2.日志請求
把所有動作都記錄在日志中,在系統發生錯誤時,重新調用這些動作恢復到之前的狀態


Command Pattern的適用場景
1.使用命令模式作為"CallBack"在面向對象系統中的替代。"CallBack"講的便是先將一個函數登記上,然后在以后調用此函數。

2.需要在不同的時間指定請求、將請求排隊。一個命令對象和原先的請求發出者可以有不同的生命期。換言之,原先的請求發出者可能已經不在了,而命令對象本身仍然是活動的。這時命令的接收者可以是在本地,也可以在網絡的另外一個地址。命令對象可以在串形化之后傳送到另外一臺機器上去。

3.系統需要支持命令的撤消(undo)。命令對象可以把狀態存儲起來,等到客戶端需要撤銷命令所產生的效果時,可以調用undo()方法,把命令所產生的效果撤銷掉。命令對象還可以提供redo()方法,以供客戶端在需要時,再重新實施命令效果。

4.如果一個系統要將系統中所有的數據更新到日志里,以便在系統崩潰時,可以根據日志里讀回所有的數據更新命令,重新調用Execute()方法一條一條執行這些命令,從而恢復系統在崩潰前所做的數據更新。

總結

Command模式是非常簡單而又優雅的一種設計模式,它的根本目的在于將“行為請求者”與“行為實現者”解耦。

Head First設計模式六-----命令模式(Command Pattern)


更多文章、技術交流、商務合作、聯系博主

微信掃碼或搜索:z360901061

微信掃一掃加我為好友

QQ號聯系: 360901061

您的支持是博主寫作最大的動力,如果您喜歡我的文章,感覺我的文章對您有幫助,請用微信掃描下面二維碼支持博主2元、5元、10元、20元等您想捐的金額吧,狠狠點擊下面給點支持吧,站長非常感激您!手機微信長按不能支付解決辦法:請將微信支付二維碼保存到相冊,切換到微信,然后點擊微信右上角掃一掃功能,選擇支付二維碼完成支付。

【本文對您有幫助就好】

您的支持是博主寫作最大的動力,如果您喜歡我的文章,感覺我的文章對您有幫助,請用微信掃描上面二維碼支持博主2元、5元、10元、自定義金額等您想捐的金額吧,站長會非常 感謝您的哦!??!

發表我的評論
最新評論 總共0條評論
主站蜘蛛池模板: 达孜县| 重庆市| 武安市| 阳谷县| 沙湾县| 库车县| 枣庄市| 嘉荫县| 邵阳县| 宁波市| 新干县| 花莲县| 垫江县| 泽州县| 南木林县| 牙克石市| 喀喇| 福鼎市| 岳阳市| 思南县| 都江堰市| 西和县| 灵山县| 日喀则市| 扶余县| 洪洞县| 沽源县| 读书| 潞西市| 衡南县| 兴和县| 京山县| 嵩明县| 崇文区| 延边| 萨迦县| 巫山县| 山西省| 扎赉特旗| 平江县| 扬州市|