java命令模式

意图

将一个请求封装为一个对象,从而可用不同的请求对客户进行参数化;对请求排队或记录日志,以及支持可撤销的操作

动机

将”发出请求的对象”和”接收与执行这些请求的对象”分隔开来。

效果:

1)、command模式将调用操作的对象和实现该操作的对象解耦

2)、可以将多个命令装配成一个复合命令,复合命令是Composite模式的一个实例

3)、增加新的command很容易,无需改变已有的类

适用性:

1)、抽象出待执行的动作以参数化某对象

2)、在不同的时刻指定、排列和执行请求。如请求队列

3)、支持取消操作

4)、支持修改日志

5)、用构建在原语操作上的高层操作构造一个系统。支持事物

参与者:

1)、Command

  声明执行操作的接口

2)、ConcreteCommand

  将一个接收者对象绑定于一个动作   调用接收者相应的操作,以实现execute

3)、Client

  创建一个具体命令对象并设定它的接收者

4)、Invoker

  要求该命令执行这个请求

5)、Receiver

  知道如何实施与执行一个请求相关的操作。任何类都可能作为一个接收者

常见应用

1、工作队列,线程池,日程安排

2、日志请求(系统恢复)

要点

1、命令模式将发出请求的对象和执行请求的对象解耦

2、在被解耦的两者之间是通过命令对象进行沟通的。命令对象封装了接收者和一个或一组动作

3、调用者通过调用命令对象的execute()发出请求,这会使得接收者的动作被调用

4、调用者可以接受命令当作参数,甚至在运行时动态的进行

5、命令可以支持撤销,做法是实现一个undo()方法来回到execute()被执行前的状态

6、宏命令是命令的一种简单的延伸,允许调用多个命令。宏方法也可以支持撤销

7、实际操作时,很常见使用”聪明”命令对象,也就是直接实现了请求,而不是将工作委托给接受者(弊端?)

8、命令也可以用来实现日志和事物系统

DEMO

Command

/**
 * 命令接口
 */
public interface Command {
    /**
     * 执行命令
     */
    public void execute();
    /**
     * 撤销命令
     */
    public void undo();
}

CreateCommand

/**
 * 命令
 */
public class CreateCommand implements Command{
    private Receiver receiver;
    private String state;

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

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

    @Override
    public void undo() {
        receiver.unAction();
    }

}

Receiver

/**
 * 命令接收者,命令真正执行人
 */
public class Receiver {
    public void action(){
        System.out.println("执行命令...");
    }

    public void unAction(){
        System.out.println("撤销命令...");
    }
}

Invoker

public class Invoker {
    /**
     * 调用者持有命令对象
     */
    private Command command;

    /**
     * 设置命令对象
     * @param command
     */
    public void setCommand(Command command) {
        this.command = command;
    }
    public Command getCommand() {
        return command;
    }

    /**
     * 执行命令
     */
    public void runCommand(){
        command.execute();
    }
    /**
     * 撤销命令
     */
    public void unDoCommand(){
        command.undo();
    }
}

Client

public class Client {
    public static void main(String[] args){
        //创建接受者
        Receiver receiver = new Receiver();
        //创建命令对象,并设置它的接受者
        Command command = new CreateCommand(receiver);

        //创建调用者,将命令对象设置进去
        Invoker invoker = new Invoker();
        invoker.setCommand(command);

        //这里可以测试一下
        invoker.runCommand();
        invoker.unDoCommand();
    }
}