命令模式

250 阅读2分钟

概念

将一系列方法调用封装,用户只需调用一个方法执行,这些封装好的方法就会被挨个执行调用。通常是将请求封装成一个对象,对请求进行排队以支持撤销等动作。优点也是降低耦合,但同时导致类膨胀。类似于java线程池中的队列,工作队列只负责取出任务,执行execute方法,不关心传入什么。

使用场景

  • 将待执行的动作以参数的形式抽象出来
  • 支持事务操作,记录和取消操作

实现方式

  • 命令角色(Command):定义命令的接口,声明执行的方法。
  • 具体命令角色(Concrete Command):实现命令接口,是“虚”的实现;通常会持有接收者,并调用接收者的功能来完成命令要执行的操作。我们可以有多个具体命令角色提供不同的命令。
  • 接收者角色(Receiver):负责具体实施和执行一个请求。任何类都可能成为一个接收者,只要它能够实现命令要求实现的相应功能。
  • 请求者(调用者)角色(Invoker):负责调用命令对象执行请求。在请求者中可维持一个数据结构记录执行过哪些命令。
  • 客户角色(Client):创建一个具体命令对象并设定该命令对象的接收者
/**
    具体接受者
**/
public class Receiver {
    // 洗手
    public void actionWashing(){
        System.out.println("执行洗手操作");
    }

    // 吃饭
    public void actionEat(){
        System.out.println("执行吃饭操作");
    }
}

/**
    抽象命令
**/
public interface Command {
    void execute();
}

/**
    洗手命令
**/
public class WashCommand implements Command {
    private Receiver receiver;

    public WashCommand(Receiver receiver){
        this.receiver = receiver;
    }

    @Override
    public void execute(){
        receiver.actionWashing();
    }
}

/**
    吃饭命令
**/
public class EatCommand implements Command {
    private Receiver receiver;

    public EatCommand(Receiver receiver){
        this.receiver = receiver;
    }

    @Override
    public void execute(){
        receiver.actionEat();
    }
}

/**
    命令请求调度者(管理各个命令之间的执行顺序)
**/
public class Invoker {
    private List<Command> commands = new ArrayList<Command>();
    public addCommand(Command command) {
        commands.add(command);
    }

    public void executeActions(){
        for(Command c : commands) {
            c.execute();
        }
    }
}

public class Client{
    public static void main(String[] args){
        Receiver receiver = new Receiver();
        Invoker invoker = new Invoker();
        invoker.addCommand(new WashCommand(receiver));
        invoker.addCommand(new EatCommand(receiver));
        invoker.action();
    }
}