天天看點

【設計模式】指令模式

一、前言

  讀完單例模式,接着品指令模式,指令模式在工程實踐中有應用,如MVC架構中使用了指令模式,還有日志系統(從異常中恢複)和事務系統都可以使用指令模式,指令模式可以解耦指令請求者和指令執行者,下面開始學習指令模式。

二、指令模式定義

  定義:指令模式将請求封裝成對象,以便使用不同的請求、隊列或者日志來參數化其他對象。指令模式也支援撤銷的操作。

  從定義可以看出,指令模式核心的概念就是講請求封裝成為對象,這樣,對象可以被傳遞,進而解耦請求者和執行者。

  指令模式的類圖如下

【設計模式】指令模式

  說明:對于類圖說明如下

  ① Client負責建立一個ConcreteCommand,并設定接受者。

  ② Invoker持有一個指令對象,并在某個時間點調用指令對象的execute方法,将請求付諸實行。

  ③ Command為所有指令聲明了一個接口,調用指令對象的execute方法,就可以讓接受者進行相關的動作,這個接口也具備一個undo方法。

  ④ ConcreteCommand定義了動作和接受者之間的綁定關系,調用者隻要調用execute方法就可以送出請求,然後由ConcreteCommand調用接受者的一個或多個動作。

  ⑤ Receiver為接受者,實作請求具體的動作,任何類都可以當接受者。

三、示例說明

  設想如下場景,家裡的電器都通過一個遙控器來控制,按下按鈕即可控制電器的開關,并且隻要在遙控的相關插口插入對應的電器子產品,即可控制相應的電器,即可很友善的進行替換。

  3.1 v1.0

  Command  

【設計模式】指令模式
【設計模式】指令模式

package com.hust.grid.leesf.command;

interface Command {
    void execute();
    void undo();
}      

View Code

  LightOnCommand

【設計模式】指令模式
【設計模式】指令模式
package com.hust.grid.leesf.command;

public class LightOnCommand implements Command {
    private Receiver light;
    
    public LightOnCommand(Receiver receiver) {
        this.light = receiver;
    }
    
    @Override
    public void execute() {
        light.on();
    }

    @Override
    public void undo() {
        light.off();
    }

}      

  LightOffCommand

【設計模式】指令模式
【設計模式】指令模式
package com.hust.grid.leesf.command;

public class LightOffCommand implements Command {
    private Receiver light;
    
    public LightOffCommand(Receiver receiver) {
        light = receiver;
    }
    
    @Override
    public void execute() {
        light.off();
    }

    @Override
    public void undo() {
        light.on();
    }
    
}      

  CeilingFanOnCommand

【設計模式】指令模式
【設計模式】指令模式
package com.hust.grid.leesf.command;

public class CeilingFanOnCommand implements Command {
    private Receiver ceilingFan;
    
    public CeilingFanOnCommand(Receiver receiver) {
        ceilingFan = receiver;
    }
    
    @Override
    public void execute() {
        ceilingFan.on();
    }

    @Override
    public void undo() {
        ceilingFan.off();
    }
}      

  CeilingFanOffCommand

【設計模式】指令模式
【設計模式】指令模式
package com.hust.grid.leesf.command;

public class CeilingFanOffCommand implements Command {
    private Receiver ceilingFan;
    
    public CeilingFanOffCommand(Receiver receiver) {
        ceilingFan = receiver;
    }
    
    @Override
    public void execute() {
        ceilingFan.off();
    }

    @Override
    public void undo() {
        ceilingFan.on();
    }
}      

  Receiver

【設計模式】指令模式
【設計模式】指令模式
package com.hust.grid.leesf.command;

public abstract class Receiver {
    protected String name;
    public Receiver(String name) {
        this.name = name;
    }
    
    public void on() {
        System.out.println(this.name + " is on");
    }
    
    public void off() {
        System.out.println(this.name + " is off");
    }
}      

  Light

【設計模式】指令模式
【設計模式】指令模式
package com.hust.grid.leesf.command;

public class Light extends Receiver {
    public Light(String name) {
        super(name);
    }
}      

  CeilingFan

【設計模式】指令模式
【設計模式】指令模式
package com.hust.grid.leesf.command;

public class CeilingFan extends Receiver {
    public CeilingFan(String name) {
        super(name);
    }
}      

  RemoteController

【設計模式】指令模式
【設計模式】指令模式
package com.hust.grid.leesf.command;

public class RemoteController {
    Command[] onCommands;
    Command[] offCommands;
    Command undoCommand;
    
    public RemoteController(int slotSize) {
        onCommands = new Command[slotSize];
        offCommands = new Command[slotSize];
    }
    
    public void setCommand(int slot, Command onCommand, Command offCommand) {
        onCommands[slot] = onCommand;
        offCommands[slot] = offCommand;
    }
    
    public void onButtonWasPushed(int slot) {
        undoCommand = onCommands[slot];
        onCommands[slot].execute();
    }
    
    public void offButtonWasPushed(int slot) {
        undoCommand = offCommands[slot];
        offCommands[slot].execute();
    }
    
    public void undoButtonWasPushed() {
        undoCommand.undo();
    }
}      

  Main(用于測試)

【設計模式】指令模式
【設計模式】指令模式
package com.hust.grid.leesf.command;

public class Main {
    public static void main(String[] args) {
        // 遙控器
        RemoteController remoteController = new RemoteController(3);

        Light livingRoomLight = new Light("LivingRoomLight");
        Light kitchenLight = new Light("KitchenLight");
        CeilingFan ceilingFan = new CeilingFan("CeilingFan");
        
        LightOnCommand livingRoomLightOnCommand = new LightOnCommand(livingRoomLight);
        LightOffCommand livingRoomLightOffCommand = new LightOffCommand(livingRoomLight);
        
        LightOnCommand kitchenLightOnCommand = new LightOnCommand(kitchenLight);
        LightOnCommand kitchenLightOffCommand = new LightOnCommand(kitchenLight);
        
        CeilingFanOnCommand ceilingFanOnCommand = new CeilingFanOnCommand(ceilingFan);
        CeilingFanOffCommand ceilingFanOffCommand = new CeilingFanOffCommand(ceilingFan);
        
        remoteController.setCommand(0, livingRoomLightOnCommand, livingRoomLightOffCommand);
        remoteController.setCommand(1, kitchenLightOnCommand, kitchenLightOffCommand);
        remoteController.setCommand(2, ceilingFanOnCommand, ceilingFanOffCommand);
        
        // 模拟遙控按下按鈕
        remoteController.onButtonWasPushed(0);        
        remoteController.onButtonWasPushed(1);
        remoteController.onButtonWasPushed(2);
        remoteController.offButtonWasPushed(2);
        // 撤銷操作
        remoteController.undoButtonWasPushed();
    }
}      

  運作結果

LivingRoomLight is on
KitchenLight is on
CeilingFan is on
CeilingFan is off
CeilingFan is on      

  說明:使用了指令模式,一切都運作良好,并且可進行撤銷操作。

  若需要添加這樣的功能,當按下按鈕時,指定的所有電器都開或者關閉,即宏指令。

  3.2 v2.0

  添加宏指令,即一次性可以執行多個指令

  MacroCommand

【設計模式】指令模式
【設計模式】指令模式
package com.hust.grid.leesf.command;

public class MacroCommand implements Command {
    private Command[] commands;
    public MacroCommand(Command[] commands) {
        this.commands = commands;
    }
    
    @Override
    public void execute() {
        for (int i = 0; i < commands.length; i++) {
            commands[i].execute();
        }
    }

    @Override
    public void undo() {
        for (int i = 0; i < commands.length; i++) {
            commands[i].undo();
        }
    }

}      

  Main(用作測試)

【設計模式】指令模式
【設計模式】指令模式
package com.hust.grid.leesf.command;

public class Main {
    public static void main(String[] args) {
        // 遙控器
        RemoteController remoteController = new RemoteController(4);

        Light livingRoomLight = new Light("LivingRoomLight");
        Light kitchenLight = new Light("KitchenLight");
        CeilingFan ceilingFan = new CeilingFan("CeilingFan");
        
        LightOnCommand livingRoomLightOnCommand = new LightOnCommand(livingRoomLight);
        LightOffCommand livingRoomLightOffCommand = new LightOffCommand(livingRoomLight);
        
        LightOnCommand kitchenLightOnCommand = new LightOnCommand(kitchenLight);
        LightOnCommand kitchenLightOffCommand = new LightOnCommand(kitchenLight);
        
        CeilingFanOnCommand ceilingFanOnCommand = new CeilingFanOnCommand(ceilingFan);
        CeilingFanOffCommand ceilingFanOffCommand = new CeilingFanOffCommand(ceilingFan);
        
        Command[] partyOn = {livingRoomLightOnCommand, kitchenLightOnCommand, ceilingFanOnCommand};
        Command[] partyOff = {livingRoomLightOffCommand, kitchenLightOffCommand, ceilingFanOffCommand};
        MacroCommand macroOnCommand = new MacroCommand(partyOn);
        MacroCommand macroOffCommand = new MacroCommand(partyOff);
        
        remoteController.setCommand(0, livingRoomLightOnCommand, livingRoomLightOffCommand);
        remoteController.setCommand(1, kitchenLightOnCommand, kitchenLightOffCommand);
        remoteController.setCommand(2, ceilingFanOnCommand, ceilingFanOffCommand);
        remoteController.setCommand(3, macroOnCommand, macroOffCommand);
        
        // 模拟遙控按下按鈕
        remoteController.onButtonWasPushed(3);
        // 撤銷操作
        remoteController.undoButtonWasPushed();
    }
}      
LivingRoomLight is on
KitchenLight is on
CeilingFan is on
LivingRoomLight is off
KitchenLight is off
CeilingFan is off      

  說明:可以看到,調用了宏指令後,一次性執行了多條指令,并且執行撤消後,會恢複到之前的狀态。

  指令模式的要點如下:

  ① 指令模式将發出的請求的對象和執行請求的對象解耦

  ② 在被解耦的兩者之間是通過指令對象進行溝通的。指令對象封裝了接受者和一個或一組動作。

  ③ 調用者通過調用指令對象的execute方法送出請求,這會使得接受者的動作被調用。

  ④ 調用者可以接受指令當做參數,甚至在運作時動态地進行。

四、總結

  對于指令模式而言,其應用也相對比較廣泛,在工程應用中有适合應用此種模式的地方,不妨使用,所有源代碼已經上傳至github,歡迎fork,謝謝各位園友的觀看~  

PS:如果您覺得閱讀本文對您有幫助,請點一下

“推薦”

按鈕,您的

,将會是我不竭的動力!

作者:

leesf 掌控之中,才會成功;掌控之外,注定失敗。

出處:http://www.cnblogs.com/leesf456/

本文版權歸作者和部落格園共有,歡迎轉載,但未經作者同意必須保留此段聲明,且在文章頁面明顯位置給出原文連接配接,否則保留追究法律責任的權利。

如果覺得本文對您有幫助,您可以請我喝杯咖啡!

【設計模式】指令模式
【設計模式】指令模式