介紹
將一個請求封裝成一個對象,從而讓用戶使用不同的請求把客戶端參數化,對請求排隊或者記錄請求日志,以及支持可撤銷的操作,
應用場景
- 需要抽象出待執行的動作,然后以參數的形式體統出來——類似過程設計中的回調機制
- 在不同的時刻指定、排序和執行的請求,一個命令對象可以有與初始請求無關的生存期
- 需要支持取消操作
- 支持修改日志
- 需要支持事務
UML
UML.png
具體代碼實現
以俄羅斯方塊中的按鍵為例
- 接收者角色
public class TetrisMachine {
public void toLeft() {
System.out.println("向左");
}
public void toRight() {
System.out.println("向右");
}
public void fastToBottom() {
System.out.println("快速下降");
}
public void transform() {
System.out.println("改變形狀");
}
}
- 抽象命令接口
public interface Command {
void execute();
}
- 具體命令類
public class FallCommand implements Command {
private TetrisMachine machine;
public FallCommand(TetrisMachine machine) {
this.machine = machine;
}
@Override
public void execute() {
machine.fastToBottom();
}
}
public class LeftCommand implements Command {
private TetrisMachine machine;
public LeftCommand(TetrisMachine machine) {
this.machine = machine;
}
@Override
public void execute() {
machine.toLeft();
}
}
public class RightCommand implements Command {
private TetrisMachine machine;
public RightCommand(TetrisMachine machine) {
this.machine = machine;
}
@Override
public void execute() {
machine.toRight();
}
}
public class TransformCommand implements Command {
private TetrisMachine machine;
public TransformCommand(TetrisMachine machine) {
this.machine = machine;
}
@Override
public void execute() {
machine.transform();
}
}
- 請求角色
public class Buttons {
private LeftCommand leftCommand;
private RightCommand rightCommand;
private FallCommand fallCommand;
private TransformCommand transformCommand;
public void setLeftCommand(LeftCommand leftCommand) {
this.leftCommand = leftCommand;
}
public void setRightCommand(RightCommand rightCommand) {
this.rightCommand = rightCommand;
}
public void setFallCommand(FallCommand fallCommand) {
this.fallCommand = fallCommand;
}
public void setTransformCommandl(TransformCommand transformCommand) {
this.transformCommand = transformCommand;
}
public void toLeft() {
leftCommand.execute();
}
public void toRight() {
rightCommand.execute();
}
public void fallTo() {
fallCommand.execute();
}
public void transform() {
transformCommand.execute();
}
}
- 客戶端
public static void main(String[] args) {
Buttons buttons = new Buttons();
TetrisMachine machine = new TetrisMachine();
LeftCommand leftCommand = new LeftCommand(machine);
RightCommand rightCommand = new RightCommand(machine);
FallCommand fallCommand = new FallCommand(machine);
TransformCommand transformCommand = new TransformCommand(machine);
buttons.setFallCommand(fallCommand);
buttons.setRightCommand(rightCommand);
buttons.setTransformCommandl(transformCommand);
buttons.setLeftCommand(leftCommand);
buttons.toRight();
buttons.toLeft();
}
- 輸出結果
輸出結果.png
其實到這里會有很多讀者會感到疑惑,明明可以只用一個類就解決的問題,硬是被解耦成多個部分,增加代碼的復雜度,為什么呢?
其實是為了設計模式的一個重要原則:對修改關閉,對擴展開放,這里大家慢慢體會。
總結
在命令模式中充分體現了幾乎所有模式的通病,就是類的膨脹,大量衍生類的創建,這是一個不可避免的問題,但是給我們帶來的好處也是非常多,更弱的耦合性,更靈敏的控制性,以及更好的擴展性,不過在實際開發中是否使用命令模式是要好好斟酌的。