定义
将一个请求或一个命令封装成一个对象,并定义命令的接收者和调用者,从而使得客户端参数化。
命令模式有三个比较重要的角色,分别是执行者 Invoker
、接收者 Receiver
和命令 Command
。
命令模式的一个突出使用场景是在 GUI 中,比如编辑框的撤销、粘贴、剪切等操作。
所以,命令模式的主要应用于将被封装好的 Command 加入队列,并提供命令的执行、撤销、恢复等一系列操作。
其优点就是,能够对被执行的命令(Command)提供有效的管理,而且调用者(Invoker)和接收者(Receiver)之间不存在强耦合关系,使得三者之间能够充分解耦。
例子
简单利用一个关机、开机的例子,来说明命令模式的一般结构。我们定义一个调用者接口:
public interface Invoker {
void request(int commandCode);
}
然后,定义接收者:
interface Receiver {
void shutdown();
void startup();
}
接下来是命令:
public interface Command {
void execute();
}
定义一个开机命令,实现 Command 接口中的方法:
public class StartUpCmd implements Command {
private Receiver receiver;
public StartUpCmd(Receiver receiver) {
this.receiver = receiver;
}
@Override
public void execute() {
System.out.println("start up...");
}
}
然后,定义一个关机的 Command:
public class ShutdownCmd implements Command {
private Receiver receiver;
public ShutdownCmd(Receiver receiver) {
this.receiver = receiver;
}
@Override
public void execute() {
receiver.shutdown();
}
}
然后,定义一个接收者计算机,用于接收命令,接收者是真正去执行某些操作的角色,而 Command 仅仅是一个命令,不提供具体 Action:
public class ComputerReceiver implements Receiver {
@Override
public void shutdown() {
System.out.println("shutdown...");
}
@Override
public void startup() {
System.out.println("start up...");
}
}
下面,看看具体命令调用者的处理:
public class CPUInvoker implements Invoker {
private HashMap<Integer, Command> commandMap;
public CPUInvoker() {
commandMap = new HashMap<>();
}
@Override
public void request(int commandCode) {
Command c = commandMap.get(commandCode);
if (c != null) {
c.execute();
}
}
public void registerCommand(int code, Command command) {
commandMap.put(code, command);
}
}
调用者仅仅发起了某个命令的请求,并能够对每个命令进行管理,比如添加、移除等行为。
定义客户端:
public class Client {
public static void main(String[] args) {
ComputerReceiver computer = new ComputerReceiver();
Command shutdown = new ShutdownCmd(computer);
Command startup = new StartUpCmd(computer);
CPUInvoker cpu = new CPUInvoker();
cpu.registerCommand(0x01, shutdown);
cpu.registerCommand(0x02, startup);
cpu.request(0x01);
}
}
从中可以看出,客户端将被封装好的命令参数化,并传给了调用者 CPUInvoker,而真正执行 Action 的 ComputerReceiver 与 命令的调用者 CPUInvoker 之间不存在过强的耦合关系。
除此之外,能够更好地对命令进行管理。
总结
命令模式是行为型设计模式之一,其优点和使用场景显而易见,并不难理解。
但是,命令模式的缺点几乎是所有设计模式的通病,也就是大量衍生类的创建,在实际项目中使用命令模式还需要斟酌。
总之,命令模式给我们提供的好处非常多,更强的灵活性,更好的扩展性,等等。在开发中,可以适当地变通,基于命令模式的前提下,减少不必要的类的创建,又能体验命令模式给我们带来的好处。
本文由Fynn_原创,未经许可,不得转载!
网友评论