天天看點

Java設計模式(18)之指令模式指令模式類型:指令模式的幾個角色:指令模式關系圖:指令模式示例:總結:指令模式的優缺點:

指令模式

将“請求”封裝成對象,以便使用不同的請求、隊列或者日志來參數化其他對象。指令模式也支援可撤銷的操作。指令模式通過這種封裝的方式實作将用戶端和接收端解耦。

類型:

行為型模式(類與類之間的行為型模式)

指令模式的幾個角色:

  • 抽象指令接口Command:定義指令的接口,聲明執行的方法。
  • 具體的指令對象ConcreteCommand:持有具體的接受者對象,完成具體的具體的指令。
  • 接受者對象Receiver:接受者對象,真正執行指令的對象。
  • 傳遞指令對象Invoker:持有指令對象,要求指令對象執行請求。
  • 用戶端對象Client:建立具體指令的對象并且設定指令對象的接受者。

指令模式關系圖:

Java設計模式(18)之指令模式指令模式類型:指令模式的幾個角色:指令模式關系圖:指令模式示例:總結:指令模式的優缺點:

指令模式示例:

本例子是呼叫小愛同學幫你開燈的例子,你對小愛同學說:小愛同學幫我打開燈,然後小愛同學讓燈自己打開了。

抽象指令接口Command:

/**
 * Create by zhaihongwei on 2018/3/30
 * 抽象的指令接口,定義具體命名的接口
 */
public interface Command {

    /**
     * 執行命名的接口
     */
    void execute();
}
           

具體的指令對象ConcreteCommand:(開燈指令,關燈指令)

/**
 * Create by zhaihongwei on 2018/3/30
 * 開燈指令
 */
public class LightOnCommand implements Command{

    private Light light;

    /**
     * 建立開燈指令的時候,傳入具體的燈對象,由燈對象操作自己
     * @param light
     */
    public LightOnCommand(Light light) {
        this.light = light;
    }

    @Override
    /**
     * 具體的燈對象調用自己的開燈方法
     */
    public void execute() {
        light.lightOn();
    }
}
           
/**
 * Create by zhaihongwei on 2018/3/30
 * 關燈指令
 */
public class LightOffCommand implements Command{

    private Light light;

    /**
     * 建立關燈指令的時候,傳入具體的燈對象,由燈對象操作自己
     * @param light
     */
    public LightOffCommand(Light light) {
        this.light = light;
    }

    @Override
    /**
     * 具體的燈對象調用自己的關燈方法
     */
    public void execute() {
        light.lightOff();
    }
}
           

傳遞指令對象Invoker:

/**
 * Create by zhaihongwei on 2018/3/30
 * 小愛同學
 */
public class XiaoAi {

    private Command command;

    /**
     * 設定具體的指令
     * @param command
     */
    public void setCommand(Command command) {
        this.command = command;
    }

    /**
     * 執行指令
     */
    public void doCommand() {
        command.execute();
    }
}
           

接受者對象Receiver:

/**
 * Create by zhaihongwei on 2018/3/30
 * 具體的電燈類
 */
public class Light {

    /**
     * 開燈方法
     */
    public void lightOn() {
        System.out.println("燈打開了!!");
    }

    /**
     * 關燈方法
     */
    public void lightOff() {
        System.out.println("燈關上了!!");
    }
}
           

用戶端對象:

/**
 * Create by zhaihongwei on 2018/3/30
 * 用戶端對象
 */
public class Client {

    public static void main(String[] args) {
        // 建立小愛同學
        XiaoAi xiaoAi = new XiaoAi();
        // 建立具體的等對象,相當于具體的指令接受者
        Light light = new Light();
        // 建立了開燈的指令,你就是指令的發起者
        System.out.println("小愛同學幫我把燈開一下!");
        LightOnCommand lightOnCommand = new LightOnCommand(light);
        // 小愛同學接受到了你發出的指令,并執行指令
        xiaoAi.setCommand(lightOnCommand);
        xiaoAi.doCommand();

        System.out.println("-------------------------------------------------");
        System.out.println("小愛同學幫我關一下燈!");
        LightOffCommand lightOffCommand = new LightOffCommand(light);
        xiaoAi.setCommand(lightOffCommand);
        xiaoAi.doCommand();

    }
}
           

測試結果:

小愛同學幫我把燈開一下!
燈打開了!!
-------------------------------------------------
小愛同學幫我關一下燈!
燈關上了!!
           

總結:

上面的例子僅僅是實作單個指令的的指令模式,而指令模式是可以相當複雜的,就比如說,你讓小愛同學幫你打開燈,并且幫你打開電視,并且打開空調等等,這時候我們可以将多個指令存儲起來,然後一次性執行。

關于NoCommand的了解:

在沒有設定具體的指令的時候将指令存儲中的對象都設定成NoCommand的,這樣做可以避免空指針異常,具體作用展現可以閱讀《Head First》 。

關于宏指令的了解:

将多個指令存儲起來,發出執行宏指令請求的之後執行存儲的所有指令。

關于指令撤銷的了解:

在我們發出某個請求并執行之後,将指令的執行狀态進行儲存,如果我們想要回歸執行這個指令之前的狀态,我們就可以通過指令撤銷的方式回歸到之前的狀态。

指令模式的優缺點:

優點:

  • 實作用戶端和接受者之間的解耦。
  • 可以動态的添加新的指令。
  • 隻需要調用同一個方法(doCommand方法)便可以實作不同的功能。

缺點:

  • 實作一個具體的指令系統,可能要建立很多的具體指令對象。

繼續閱讀