一、前言
讀完單例模式,接着品指令模式,指令模式在工程實踐中有應用,如MVC架構中使用了指令模式,還有日志系統(從異常中恢複)和事務系統都可以使用指令模式,指令模式可以解耦指令請求者和指令執行者,下面開始學習指令模式。
二、指令模式定義
定義:指令模式将請求封裝成對象,以便使用不同的請求、隊列或者日志來參數化其他對象。指令模式也支援撤銷的操作。
從定義可以看出,指令模式核心的概念就是講請求封裝成為對象,這樣,對象可以被傳遞,進而解耦請求者和執行者。
指令模式的類圖如下

說明:對于類圖說明如下
① Client負責建立一個ConcreteCommand,并設定接受者。
② Invoker持有一個指令對象,并在某個時間點調用指令對象的execute方法,将請求付諸實行。
③ Command為所有指令聲明了一個接口,調用指令對象的execute方法,就可以讓接受者進行相關的動作,這個接口也具備一個undo方法。
④ ConcreteCommand定義了動作和接受者之間的綁定關系,調用者隻要調用execute方法就可以送出請求,然後由ConcreteCommand調用接受者的一個或多個動作。
⑤ Receiver為接受者,實作請求具體的動作,任何類都可以當接受者。
三、示例說明
設想如下場景,家裡的電器都通過一個遙控器來控制,按下按鈕即可控制電器的開關,并且隻要在遙控的相關插口插入對應的電器子產品,即可控制相應的電器,即可很友善的進行替換。
3.1 v1.0
Command
package com.hust.grid.leesf.command;
interface Command {
void execute();
void undo();
}
View Code
LightOnCommand
package com.hust.grid.leesf.command;
public class LightOnCommand implements Command {
private Receiver light;
public LightOnCommand(Receiver receiver) {
this.light = receiver;
}
@Override
public void execute() {
light.on();
}
@Override
public void undo() {
light.off();
}
}
LightOffCommand
package com.hust.grid.leesf.command;
public class LightOffCommand implements Command {
private Receiver light;
public LightOffCommand(Receiver receiver) {
light = receiver;
}
@Override
public void execute() {
light.off();
}
@Override
public void undo() {
light.on();
}
}
CeilingFanOnCommand
package com.hust.grid.leesf.command;
public class CeilingFanOnCommand implements Command {
private Receiver ceilingFan;
public CeilingFanOnCommand(Receiver receiver) {
ceilingFan = receiver;
}
@Override
public void execute() {
ceilingFan.on();
}
@Override
public void undo() {
ceilingFan.off();
}
}
CeilingFanOffCommand
package com.hust.grid.leesf.command;
public class CeilingFanOffCommand implements Command {
private Receiver ceilingFan;
public CeilingFanOffCommand(Receiver receiver) {
ceilingFan = receiver;
}
@Override
public void execute() {
ceilingFan.off();
}
@Override
public void undo() {
ceilingFan.on();
}
}
Receiver
package com.hust.grid.leesf.command;
public abstract class Receiver {
protected String name;
public Receiver(String name) {
this.name = name;
}
public void on() {
System.out.println(this.name + " is on");
}
public void off() {
System.out.println(this.name + " is off");
}
}
Light
package com.hust.grid.leesf.command;
public class Light extends Receiver {
public Light(String name) {
super(name);
}
}
CeilingFan
package com.hust.grid.leesf.command;
public class CeilingFan extends Receiver {
public CeilingFan(String name) {
super(name);
}
}
RemoteController
package com.hust.grid.leesf.command;
public class RemoteController {
Command[] onCommands;
Command[] offCommands;
Command undoCommand;
public RemoteController(int slotSize) {
onCommands = new Command[slotSize];
offCommands = new Command[slotSize];
}
public void setCommand(int slot, Command onCommand, Command offCommand) {
onCommands[slot] = onCommand;
offCommands[slot] = offCommand;
}
public void onButtonWasPushed(int slot) {
undoCommand = onCommands[slot];
onCommands[slot].execute();
}
public void offButtonWasPushed(int slot) {
undoCommand = offCommands[slot];
offCommands[slot].execute();
}
public void undoButtonWasPushed() {
undoCommand.undo();
}
}
Main(用于測試)
package com.hust.grid.leesf.command;
public class Main {
public static void main(String[] args) {
// 遙控器
RemoteController remoteController = new RemoteController(3);
Light livingRoomLight = new Light("LivingRoomLight");
Light kitchenLight = new Light("KitchenLight");
CeilingFan ceilingFan = new CeilingFan("CeilingFan");
LightOnCommand livingRoomLightOnCommand = new LightOnCommand(livingRoomLight);
LightOffCommand livingRoomLightOffCommand = new LightOffCommand(livingRoomLight);
LightOnCommand kitchenLightOnCommand = new LightOnCommand(kitchenLight);
LightOnCommand kitchenLightOffCommand = new LightOnCommand(kitchenLight);
CeilingFanOnCommand ceilingFanOnCommand = new CeilingFanOnCommand(ceilingFan);
CeilingFanOffCommand ceilingFanOffCommand = new CeilingFanOffCommand(ceilingFan);
remoteController.setCommand(0, livingRoomLightOnCommand, livingRoomLightOffCommand);
remoteController.setCommand(1, kitchenLightOnCommand, kitchenLightOffCommand);
remoteController.setCommand(2, ceilingFanOnCommand, ceilingFanOffCommand);
// 模拟遙控按下按鈕
remoteController.onButtonWasPushed(0);
remoteController.onButtonWasPushed(1);
remoteController.onButtonWasPushed(2);
remoteController.offButtonWasPushed(2);
// 撤銷操作
remoteController.undoButtonWasPushed();
}
}
運作結果
LivingRoomLight is on
KitchenLight is on
CeilingFan is on
CeilingFan is off
CeilingFan is on
說明:使用了指令模式,一切都運作良好,并且可進行撤銷操作。
若需要添加這樣的功能,當按下按鈕時,指定的所有電器都開或者關閉,即宏指令。
3.2 v2.0
添加宏指令,即一次性可以執行多個指令
MacroCommand
package com.hust.grid.leesf.command;
public class MacroCommand implements Command {
private Command[] commands;
public MacroCommand(Command[] commands) {
this.commands = commands;
}
@Override
public void execute() {
for (int i = 0; i < commands.length; i++) {
commands[i].execute();
}
}
@Override
public void undo() {
for (int i = 0; i < commands.length; i++) {
commands[i].undo();
}
}
}
Main(用作測試)
package com.hust.grid.leesf.command;
public class Main {
public static void main(String[] args) {
// 遙控器
RemoteController remoteController = new RemoteController(4);
Light livingRoomLight = new Light("LivingRoomLight");
Light kitchenLight = new Light("KitchenLight");
CeilingFan ceilingFan = new CeilingFan("CeilingFan");
LightOnCommand livingRoomLightOnCommand = new LightOnCommand(livingRoomLight);
LightOffCommand livingRoomLightOffCommand = new LightOffCommand(livingRoomLight);
LightOnCommand kitchenLightOnCommand = new LightOnCommand(kitchenLight);
LightOnCommand kitchenLightOffCommand = new LightOnCommand(kitchenLight);
CeilingFanOnCommand ceilingFanOnCommand = new CeilingFanOnCommand(ceilingFan);
CeilingFanOffCommand ceilingFanOffCommand = new CeilingFanOffCommand(ceilingFan);
Command[] partyOn = {livingRoomLightOnCommand, kitchenLightOnCommand, ceilingFanOnCommand};
Command[] partyOff = {livingRoomLightOffCommand, kitchenLightOffCommand, ceilingFanOffCommand};
MacroCommand macroOnCommand = new MacroCommand(partyOn);
MacroCommand macroOffCommand = new MacroCommand(partyOff);
remoteController.setCommand(0, livingRoomLightOnCommand, livingRoomLightOffCommand);
remoteController.setCommand(1, kitchenLightOnCommand, kitchenLightOffCommand);
remoteController.setCommand(2, ceilingFanOnCommand, ceilingFanOffCommand);
remoteController.setCommand(3, macroOnCommand, macroOffCommand);
// 模拟遙控按下按鈕
remoteController.onButtonWasPushed(3);
// 撤銷操作
remoteController.undoButtonWasPushed();
}
}
LivingRoomLight is on
KitchenLight is on
CeilingFan is on
LivingRoomLight is off
KitchenLight is off
CeilingFan is off
說明:可以看到,調用了宏指令後,一次性執行了多條指令,并且執行撤消後,會恢複到之前的狀态。
指令模式的要點如下:
① 指令模式将發出的請求的對象和執行請求的對象解耦
② 在被解耦的兩者之間是通過指令對象進行溝通的。指令對象封裝了接受者和一個或一組動作。
③ 調用者通過調用指令對象的execute方法送出請求,這會使得接受者的動作被調用。
④ 調用者可以接受指令當做參數,甚至在運作時動态地進行。
四、總結
對于指令模式而言,其應用也相對比較廣泛,在工程應用中有适合應用此種模式的地方,不妨使用,所有源代碼已經上傳至github,歡迎fork,謝謝各位園友的觀看~
PS:如果您覺得閱讀本文對您有幫助,請點一下
“推薦”按鈕,您的
,将會是我不竭的動力!
作者:
leesf 掌控之中,才會成功;掌控之外,注定失敗。出處:http://www.cnblogs.com/leesf456/
本文版權歸作者和部落格園共有,歡迎轉載,但未經作者同意必須保留此段聲明,且在文章頁面明顯位置給出原文連接配接,否則保留追究法律責任的權利。
如果覺得本文對您有幫助,您可以請我喝杯咖啡!