命令模式(Command Pattern):
将一个请求封装为一个对象,从而使你可用不同的请求对客户进行参数化,对请求排队或记录请求日志,以及支持可取消的操作。(Encapsulate a request as an object,thereby letting you parameterize clients with different requests, queue or log requests, and support undoable operations.)
何时使用:
在某些场合,比如要对行为进行"记录、撤销/重做、事务"等处理,这种无法抵御变化的紧耦合是不合适的。在这种情况下,如何将"行为请求者"与"行为实现者"解耦?将一组行为抽象为对象,可以实现二者之间的松耦合。
主要解决:
在软件系统中,行为请求者与行为实现者通常是一种紧耦合的关系,但某些场合,比如需要对行为进行记录、撤销或重做、事务等处理时,这种无法抵御变化的紧耦合的设计就不太合适。
开发中常见的场景:
Struts2中,action的整个调用过程中就有命令模式。Struts其实就是一种将请求和呈现分离的技术,其中必然涉及命令模式的思想。比如 : struts 1 中的 action 核心控制器 ActionServlet 只有一个,相当于 Invoker,而模型层的类会随着不同的应用有不同的模型类,相当于具体的 Command。
数据库事务机制的底层实现
命令的撤销和恢复
经典的命令模式包括4个角色:
Command:定义命令的统一接口
ConcreteCommand:Command接口的实现者,用来执行具体的命令,某些情况下可以直接用来充当Receiver。
Receiver:命令的实际执行者
Invoker:命令的请求者,是命令模式中最重要的角色。这个角色用来对各个命令进行控制。
命令模式的代码大致可分为5步:
步骤1:定义接收者 (Receiver) ,接收者执行与请求相关的操作,具体实现对请求的业务处理;未抽象前,实际执行操作内容的对象。
/**
* 真正的命令的执行者
*/
public class Receiver {
public void action(){
System.out.println("Receiver.action()");
}
}
步骤2:定义抽象命令类(Command)
public interface Command {
/**
* 这个方法是一个返回结果为空的方法。
* 实际项目中,可以根据需求设计多个不同的方法
*/
void execute();
}
步骤3:定义具体命令类(ConcreteCommand)
public class ConcreteCommand implements Command {
private Receiver receiver; //命令的真正的执行者
public ConcreteCommand(Receiver receiver) {
super();
this.receiver = receiver;
}
@Override
public void execute() {
//命令真正执行前或后,执行相关的处理!
receiver.action();
}
}
步骤4:定义调用者/请求者(Invoker)
/**
* 调用者/发起者
*/
public class Invoke {
//也可以通过容器List<Command>容纳很多命令对象,进行批处理。
// 数据库底层的事务管理就是类似的结构!
private Command command;
public Invoke(Command command) {
super();
this.command = command;
}
//业务方法 ,用于调用命令类的方法
public void call(){
command.execute();
}
}
步骤5:定义客户类(Client)
/**
* 测试
*/
public class Client {
public static void main(String[] args) {
Command c = new ConcreteCommand(new Receiver());
Invoke i = new Invoke(c);
i.call();
//new Receiver().action();
}
}