命令模式(Command)
命令模式是一种行为设计模式,
它可以将请求转换为一个包含与请求相关的所有信息的独立对象。
转换让你能根据不同的请求将方法参数化,并且能够支持排队、延迟执行、记录日志、撤销等附加控制功能。
优点:
缺点:
命令抽象类
public abstract class Command {
/**
* 实际接收者。 作为示例,这里忽略了请求的参数
*/
protected GameEngine gameEngine;
public Command(GameEngine gameEngine) {
this.gameEngine = gameEngine;
}
/**
* 大部分命令只处理如何将请求传递到接收者的细节
* 如有需要,也可以在这个类里添加一些附加功能,如撤销、队列、延迟等。
*/
public abstract String execute();
}
具体命令
public class CommandQ extends Command{
public CommandQ(GameEngine gameEngine) {
super(gameEngine);
}
@Override
public String execute() {
// 将请求传递到接收者的细节
return gameEngine.attack();
}
}
public class CommandW extends Command{
public CommandW(GameEngine gameEngine) {
super(gameEngine);
}
@Override
public String execute() {
return gameEngine.vertigo();
}
}
public class CommandE extends Command{
public CommandE(GameEngine gameEngine) {
super(gameEngine);
}
@Override
public String execute() {
return gameEngine.sleep();
}
}
public class CommandR extends Command {
public CommandR(GameEngine gameEngine) {
super(gameEngine);
}
@Override
public String execute() {
// 将请求传递到接收者的细节,也可以做些别的操作
return gameEngine.attack() + gameEngine.fear();
}
}
接收者 (Receiver)
public class GameEngine {
/**
* 接收者自己会完成实际的工作。
*/
public String attack() {
return "敌方扣血";
}
public String vertigo() {
return "敌方眩晕";
}
public String sleep() {
return "敌方沉睡";
}
public String fear() {
return "敌方恐惧";
}
}
测试代码
public class CommandTest {
@Test
public void test() {
// 游戏引擎,负责底层逻辑操作
GameEngine gameEngine = new GameEngine();
Assertions.assertEquals("敌方扣血",new CommandQ(gameEngine).execute());
Assertions.assertEquals("敌方眩晕",new CommandW(gameEngine).execute());
Assertions.assertEquals("敌方沉睡",new CommandE(gameEngine).execute());
Assertions.assertEquals("敌方扣血敌方恐惧",new CommandR(gameEngine).execute());
/**
* 利用命令模式,可以轻松的实现队列功能(这里未实现)
* 例如客户端输入一个连招命令 “WQER” 的文本,触发者将命令解码后按照顺序执行
* 撤销重做、延迟、记录历史等同理。
*/
}
}
Runnable 为命令抽象类, 只要是实现了 Runnable 接口的类都为具体命令角色。
Thread 就是调用者(Invoker),它提供了start,join,interrupt 等方法来控制“命令”也就是 Runnable 的执行。
// 相当于 Command
public interface Runnable {
// 相当于 execute()
public abstract void run();
}
更具体点的例子是 ThreadPoolExecutor。
ThreadPoolExecutor 它本身是一个调用者,它持有一个命令队列,客户端可以向他提交要执行的命令。
public interface Executor {
void execute(Runnable command);
}
public class ThreadPoolExecutor extends AbstractExecutorService {
//...
/**
* Runnable:任务抽象,也就是“命令”;
* BlockingQueue:任务阻塞队列,它实际上就是模式中的“命令队列”。
*/
private final BlockingQueue<Runnable> workQueue;
//...
}
以上代码与文章会同步到 github 仓库:
/chenbihao/Design-Patterns