设计模式学习笔记(7)——命令模式

版权声明:本文为博主原创,未经博主允许不得转载。 https://blog.csdn.net/weixin_36904568/article/details/89929165

1. 定义

又称为行动模式或交易模式。把一个请求或者操作封装到一个对象中,允许系统使用不同的请求把客户端参数化,对请求排队或者记录请求日志可以提供命令的撤销和恢复功能。

  • 发出命令的责任:请求的一方发出请求要求执行一个命令
  • 执行命令的责任:接收的一方收到请求,并执行操作
  • 由协调者在中间进行协调

使用

  • 具体接受者
    • 具体接受动作
  • 抽象命令接口
  • 具体命令对象
    • 使用堆栈记录过去的状态
    • 接受者
    • 公开执行方法(接受者需要执行的动作集合)
    • 公开撤销方法(状态出栈,接受者执行返回到该状态的对应动作集合)
  • 协调者
    • 使用堆栈记录过去的状态
    • 保存多个命令对象
    • 执行命令:命令对象中的函数
      • 调用接受者的动作
      • 当前的命令入栈
    • 撤销命令
      • 命令出栈,调用其撤销动作
  • 业务
    • 客户把封装了具体接受者的具体命令对象传递给调用者
    • 调用者执行命令(命令对象中的函数),调用接受者的动作

(1)接受者

package CommandPattern;

/**
 * 接受者A
 */
public class ReceiverA {

    public static final int MAX = 1;

    public static final int MIN = 0;

    //状态
    private int states;

    public ReceiverA(){
        this.states = MIN;
    }

    //操作
    public void actionToMax(){
        System.out.println("A接收到命令并将其变大");
        this.states = MAX;
    }

    //操作
    public void actionToMin(){
        System.out.println("A接收到命令并将其变小");
        this.states = MIN;
    }

    public int getStates() {
        return states;
    }
}

(2)命令

package CommandPattern;

/**
 * 抽象命令
 */
public interface Command {

    //执行命令
    public void execute();

    //撤销命令
    public void undo();
}

package CommandPattern;

import java.util.Stack;

/**
 * 具体命令A
 */
public class CommandA_MAX implements Command {

    private ReceiverA receiverA;

    private Stack<Integer> stack;

    public CommandA_MAX(ReceiverA receiverA) {
        this.receiverA = receiverA;
        stack = new Stack<>();
    }

    //让接受者执行相关的操作
    @Override
    public void execute() {
        //记录当前状态,方便撤销
        stack.push(receiverA.getStates());
        receiverA.actionToMax();
    }

    //让接受者撤销操作
    @Override
    public void undo() {
        int state = stack.pop();
        switch (state) {
            case ReceiverA.MIN:
                receiverA.actionToMin();
                break;
            case ReceiverA.MAX:
                receiverA.actionToMax();
                break;
        }
    }
}

package CommandPattern;

import java.util.Stack;

/**
 * 具体命令A
 */
public class CommandA_MIN implements Command {

    private ReceiverA receiverA;

    private Stack<Integer> stack;

    public CommandA_MIN(ReceiverA receiverA) {
        this.receiverA = receiverA;
        stack = new Stack<>();
    }

    //让接受者执行相关的操作
    @Override
    public void execute() {
        //记录当前状态,方便撤销
        stack.push(receiverA.getStates());
        receiverA.actionToMin();
    }

    //让接受者撤销操作
    @Override
    public void undo() {
        int state = stack.pop();
        switch (state) {
            case ReceiverA.MIN:
                receiverA.actionToMin();
                break;
            case ReceiverA.MAX:
                receiverA.actionToMax();
                break;
        }
    }
}

(3)协调者

package CommandPattern;

import java.util.ArrayList;
import java.util.List;
import java.util.Stack;

/**
 * 协调者
 */
public class Invoker {

    private List<Command> commands;

    private Stack<Command> stack;

    public Invoker(){
        stack = new Stack<>();
        commands = new ArrayList<>();
    }

    public void setCommand(Command command) {
        commands.add(command);
    }

    //执行对应的命令
    public void invoke(int i){
        Command command = commands.get(i);
        stack.push(command);
        command.execute();
    }

    //撤销命令
    public void unInvoke(){
        Command command = stack.pop();
        command.undo();
    }
}

(4)测试

package CommandPattern;

public class Test {
    public static void main(String[] args) {
        ReceiverA receiverA = new ReceiverA();
        CommandA_MAX commandA_max = new CommandA_MAX(receiverA);
        CommandA_MIN commandA_min = new CommandA_MIN(receiverA);
        Invoker invoker = new Invoker();
        invoker.setCommand(commandA_max);
        invoker.setCommand(commandA_min);
        invoker.invoke(0);
        invoker.unInvoke();
        invoker.invoke(1);
        invoker.unInvoke();
    }
}

3. 特点

  • 容易扩展新的命令
  • 较容易地设计一个命令队列
  • 容易地实现对请求的撤销和恢复
  • 较容易地将命令记入日志

4. 宏命令

宏命令作为一个包含了一组具体命令的具体命令

  • 在执行宏命令时,执行它包含的所有命令
  • 在撤销宏命令时,撤销它包含的所有命令
package CommandPattern;

import java.util.ArrayList;
import java.util.List;
import java.util.Stack;

/**
 * 宏命令,一次性执行所有命令
 */
public class MacroCommand implements Command{

    private List<Command> commands;

    private Stack<Command> stack;

    public MacroCommand(){
        commands = new ArrayList<>();
        stack = new Stack<>();
    }

    public void setCommand(Command command) {
        commands.add(command);
    }

    @Override
    public void execute() {
        for (Command command:
             commands) {
            command.execute();
            stack.push(command);
        }
    }

    @Override
    public void undo() {
        while (!stack.isEmpty()){
            Command command = stack.pop();
            command.undo();
        }
    }
}

5. 队列请求

工作队列存放一系列命令,线程从队列中取出命令并执行,然后再执行下一条命令
可以有效限制线程数目

6. 日志请求

  • 命令在执行的时候,通过记录方式,将日志存储在磁盘上
  • 系统异常时,命令利用磁盘的日志,通过加载方式,重新加载对象并执行命令

猜你喜欢

转载自blog.csdn.net/weixin_36904568/article/details/89929165