設計模式之命令模式

模式定義:

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

       命令模式可以對發送者額接受者完全解耦,發送者也接收者之間並沒有直接的聯繫,發送者只需要知道如何發送請求,不需要關心請求是如何完成了。這就是命令模式,命令模式將方法調用給封裝起來了。




模式結構



模式實現
public class OrderMode {

    /**
     * 命令接口
     */
    interface Command {
        void execute();
    }

    /**
     * lol之小魚人
     */
    class Fish {
        public void q() {
            System.out.println("淘氣打擊");
        }

        public void w() {
            System.out.println("海石三叉戟");
        }

        public void e() {
            System.out.println("古靈精怪");
        }

        public void r() {
            System.out.println("巨鯊強襲");
        }
    }

    /**
     * 默認命令
     */
    class NoCommand implements Command {
        @Override
        public void execute() {
            System.out.println("no command");
        }
    }

    /**
     * 技能q
     */
    class Q implements Command {
        private Fish fish;

        public Q(Fish fish) {
            this.fish = fish;
        }

        @Override
        public void execute() {
            fish.q();
        }
    }

    /**
     * 技能w
     */
    class W implements Command {
        private Fish fish;

        public W(Fish fish) {
            this.fish = fish;
        }

        @Override
        public void execute() {
            fish.w();
        }
    }

    /**
     * 技能e
     */
    class E implements Command {
        private Fish fish;

        public E(Fish fish) {
            this.fish = fish;
        }

        @Override
        public void execute() {
            fish.e();
        }
    }

    /**
     * 大招R
     */
    class R implements Command {
        private Fish fish;

        public R(Fish fish) {
            this.fish = fish;
        }

        @Override
        public void execute() {
            fish.r();
        }
    }

    /**
     * 控制器
     */
    class Controller {
        /**
         * 棧,用於存儲歷史命令
         */
        Stack<Command> commandStack;
        /**
         * 保持當前命令,方便下一次命令到達時存儲
         */
        Command preCommand;

        public Controller() {
            commandStack = new Stack<>(10);
            preCommand = new NoCommand();
        }

        /**
         * 設置命令
         *
         * @param command
         */
        public void setCommand(Command command) {
            commandStack.push(preCommand);
            preCommand = command;
            command.execute();

        }

        /**
         * 回到上一個命令
         */
        public void undo() {
            Command command = commandStack.pop();
            if (command == null) {
                command = new NoCommand();
            }
            command.execute();
        }
    }

    /**
     * 測試類
     */
    @Test
    public void observerTest() {
        Fish fish = new Fish();
        Q q = new Q(fish);
        W w = new W(fish);
        E e = new E(fish);
        R r = new R(fish);
        Controller controller = new Controller();
        controller.setCommand(q);
        controller.setCommand(w);
        controller.setCommand(e);
        controller.setCommand(r);
        controller.undo();
        controller.undo();
        controller.setCommand(q);
        controller.undo();
        controller.undo();
    }

}

class Stack<T> {
    /**
     * 存儲數據
     */
    private Object[] data;
    /**
     * 棧頂值及元素個數
     */
    private int top = 0;
    /**
     * 棧大小
     */
    private int size;

    public Stack(int size) {
        this.size = size;
        data = new Object[size];
        top = 0;
    }

    /**
     * 壓棧
     *
     * @param t
     */
    public synchronized void push(T t) {
        if (top >= size) {
            System.arraycopy(data, 1, data, 0, --top);
        }
        data[top++] = t;
    }

    /**
     * 出棧
     *
     * @return
     */
    public synchronized T pop() {
        if (top <= 0) {
            return null;
        }
        T t = (T) data[--top];
        return t;
    }

    /**
     * 獲取元素數
     *
     * @return
     */
    public int getSize() {
        return top < 0 ? 0 : top;
    }
}



模式優點:

1、降低了系統耦合度
2、新的命令可以很容易添加到系統中去
3、命令模式支持撤銷

模式缺點:

1、使用命令模式可能會導致某些系統有過多的具體命令類

適用場景:

1、系統需要將請求調用者和請求接收者解耦,使得調用者和接收者不直接交互
2、系統需要在不同的時間指定請求、將請求排隊和執行請求
3、系統需要支持命令的撤銷(Undo)操作和恢復(Redo)操作
4、系統需要將一組操作組合在一起,即支持宏命令

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章