定義
命令模式將"請求"封裝成對象,以便使用不同的請求、隊列或者日誌來參數化其它對象。命令模式也支持可撤銷的操作。
命令模式設計圖
模式的意義
命令模式,主要的是將請求對象和執行對象進行解耦,也就是類圖裏面的Invoker和Receiver,這個模式主切入的點很小,但是應用很廣,也是解耦思想一個比較重要的模式。
// 命令接口
public interface Command {
void execute();
void undo();
}
// 開燈功能
public class LightOnCommand implements Command {
private Light light;
public LightOnCommand(Light light) {
this.light = light;
}
public void execute() {
light.on();
}
public void undo() {
light.off();
}
// 關燈命令
public class LightOffCommand implements Command {
private Light light;
public LightOffCommand(Light light) {
this.light = light;
}
public void execute() {
light.off();
}
public void undo() {
light.on();
}
}
public class RemoteInvoker {
/**
* 開關命令數組,模擬有很多對開關數組
*/
private Command[] onCommands;
private Command[] offCommands;
private Command undoCommand;
public RemoteInvoker(int length) {
// 有幾組開關,就設置多少數組
onCommands = new Command[length];
offCommands = new Command[length];
// 把每個命令初始化成空命令,避免空指針異常
Command noCommand = new NoCommand();
undoCommand = noCommand;
for (int i = 0; i < length; i++) {
onCommands[i] = noCommand;
offCommands[i] = noCommand;
}
}
public void setCommond(int slot, Command onCommand, Command offCommand) {
onCommands[slot] = onCommand;
offCommands[slot] = offCommand;
}
public void onButton(int slot) {
onCommands[slot].execute();
undoCommand = onCommands[slot];
}
public void offButton(int slot) {
offCommands[slot].execute();
undoCommand = offCommands[slot];
}
public void undoButton() {
undoCommand.undo();
}
}
客戶端
public class RemoteClient {
public static void main(String[] args) {
// 1、創建接收者
Light light = new Light();
// 2、創建命令對象
LightOnCommand lightOnCommand = new LightOnCommand(light);
LightOffCommand lightOffCommand = new LightOffCommand(light);
// 3、創建一組開關並用命令對象裝載它
RemoteInvoker invoker = new RemoteInvoker(1);
invoker.setCommond(0, lightOnCommand, lightOffCommand);
// 4、測試
invoker.onButton(0);
invoker.offButton(0);
invoker.undoButton();
}
}
隊列
命令可以將運算打包,放入一個我們設置的工作隊列裏面,一端負責添加命令,然後另一端則是線程,線程從隊列中取出一個命令,調用他的execute()方法,等待這個調用完成,然後將此命令對象丟棄,再取出下一個命令。我們之前用Redis設計搶紅包的時候,就是將用戶搶到的紅包對象放到隊列裏面,然後由線程循環的將這個對象消耗掉,雖然沒有利用命令繼承,但也是這種概念的簡化版。