Skip to content

命令模式

ZHI-XINHUA edited this page Jan 11, 2019 · 1 revision

命令模式(Commond)

命令模式是把一个请求或者操作封装到一个对象,从而使我们可用不同的请求对客户端进行参数化;对请求排队或者记录请求日志,以及支持可撤销和恢复操作。 也称为:动作action模式、事物transaction模式

命令模式是对命令的封装。命令模式把发出去命令的责任和执行命令的责任分隔开,委派给不同的对象。

每一个命令都是一个操作:请求的一方发出请求要求执行一个操作;接收的一方收到请求,并执行。命令模式允许请求的一方和接受的一方独立开来,使得请求的一方不必知道接收请求的一方的接口,更不必知道请求是怎么被接收,以及操作是否被执行、何时被执行,以及是怎样被执行的。

命令运行请求的一方和接受的一方能够独立演化,从而具有以下优点:

  • 命令模式使新的命令很容易被加入到系统里
  • 运行接收请求的一方决定是否否决(Veto)请求
  • 能较容易地设计一个命令队列
  • 可以容易地实现请求的Undo和Redo
  • 在需要的情况下,可以较容易地加入记录日志

一个简单的例子说明:

一、模式的角色

  • 命令角色(Commond):声明了一个给所有具有命令类的抽象接口
  • 具体命令角色(ConcreteCommand):定义一个接受者和行为之间的弱耦合;负责调用接受者的响应操作
  • 请求者角色(Invoker):调用者/发起者,负责调用命令对象执行请求
  • 接收者角色(Receiver):负责具体实施和执行一个请求,真正的命令的执行者
  • 客户(client):创建具体命令和确定具体的接受者

二、代码实现

uml:

(1)Command 命令接口


/**
 * 命令角色:声明了一个给所有具有命令类的抽象接口。
 */
public interface Command {

    /**
     * 执行命令方法
     * 实际项目中,可以根据需求设计多个不同的方法
     */
    void excute();
}

(2)ConcreteCommand 具体命令

/**
 * 具体命令角色:定义一个接受者和行为之间的弱耦合;负责调用接受者的响应操作
 */
public class ConcreteCommand implements Command {
    //命令的真正的执行者
    private Receiver receiver;

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

    //命令真正执行
    @Override
    public void excute() {
        System.out.println("===记录命令执行前的日志====>");
        receiver.action();
        System.out.println("===记录命令执行后的日志====>");
    }
}

(3)Invoker 调用者/发起者

/**
 * 调用者/发起者
 * 请求者角色:负责调用命令对象执行请求
 */
public class Invoker {

    //也可以通过容器List<Command>容纳很多命令对象,进行批处理。数据库底层的事务管理就是类似的结构!
    Command command;

    public Invoker(Command command){
        this.command = command;
    }

    /**
     * 业务方法 ,用于调用命令类的方法
     */
    public void call(){
        command.excute();
    }
}

(4)Receiver 真正的命令的执行者

/**
 * 真正的命令的执行者
 * 接受者角色:负责具体实施和执行一个请求
 */
public class Receiver {

    public void action(){
        System.out.println(" Receiver>action");
    }
}

(5)客户(client):创建具体命令和确定具体的接受者

public class ClientTest {
    public static void main(String[] args) {
        //创建一个接受者
        Receiver receiver = new Receiver();
        //创建命令,并且给接受者执行
        Command command = new ConcreteCommand(receiver);

        //命令发起人,发起命令
        Invoker invoker = new Invoker(command);
        invoker.call();
    }
}

时序图:

三、开发中常见的场景

  • Struts2中,action的整个调用过程中就有命令模式
  • 数据库事务机制的底层实现
  • 命令的撤销和恢复
Clone this wiki locally