命令模式 將“請求”封裝成對象,以便使用不同的請求、隊列或者日誌來參數化其他對象。命令模式也支持可撤銷的操作。 說明: 1、命令模式將發出請求的對象和執行請求的對象解耦; 2、在被解耦的兩者之間是通過命令對象進行溝通的。命令對象封裝了接受者和一個或一組動作; 3、調用者通過調用命令對象的execut ...
命令模式 將“請求”封裝成對象,以便使用不同的請求、隊列或者日誌來參數化其他對象。命令模式也支持可撤銷的操作。 說明: 1、命令模式將發出請求的對象和執行請求的對象解耦; 2、在被解耦的兩者之間是通過命令對象進行溝通的。命令對象封裝了接受者和一個或一組動作; 3、調用者通過調用命令對象的execute()發出請求,這會使得接受者的動作被調用; 4、調用者可以接受命令當做參數,甚至在運行時動態地進行; 5、命令可以支持撤銷,做法事實現一個undo()方法來回到exexcute()被執行前的狀態; 6、命令模式也可以用來實現日誌和事物系統; 優點: 1、降低對象之間的耦合度; 2、新的命令可以很容易地加入到系統中; 3、可以比較容易地設計一個組合命令; 4、調用同一方法實現不同的功能。 缺點: 使用命令模式可能會導致某些系統有過多的具體命令類。因為針對每一個命令都需要設計一個具體命令類,因此某些系統可能需要大量具體命令類,這將影響命令模式的使用。 場景: 1、系統需要將請求調用者和請求接收者解耦,使得調用者和接收者不直接交互; 2、系統需要在不同的時間指定請求、將請求排隊和執行請求; 3、系統需要支持命令的撤銷(Undo)操作和恢復(Redo)操作; 4、系統需要將一組操作組合在一起,即支持巨集命令; 例子: 錄音機有播音(Play)、倒帶(Rewind)和停止(Stop)功能,錄音機的鍵盤便是請求者(Invoker)角色;Leslie是客戶端角色,而錄音機便是接收者角色。Command類扮演抽象命令角色,而PlayCommand、StopCommand和RewindCommand便是具體命令類。Leslie不需要知道播音(play)、倒帶(rewind)和停止(stop)功能是怎麼具體執行的,這些命令執行的細節全都由鍵盤(Keypad)具體實施。Leslie只需要在鍵盤上按下相應的鍵便可以了。
/** * 命令介面。 * 所有的命令對象需要實現該介面。 * */ public interface Commond { public void execute(); } |
/** * 錄音機--命令接受者 * */ public class AudioPlayer { public void play() { System.out.println("播放......"); } public void stop() { System.out.println("暫停......"); } public void rewind() { System.out.println("倒帶......"); } } |
/** * 錄音機播放命令 * 具體命令角色類 * */ public class PlayCommond implements Commond{ AudioPlayer player; public PlayCommond(AudioPlayer player) { this.player = player; } // 調用接收對象(錄音機)的 play() 方法 public void execute() { player.play(); } } |
/** * 錄音機倒帶命令 * 具體命令角色類 * */ public class RewindCommond implements Commond{ AudioPlayer player; public RewindCommond(AudioPlayer player) { this.player = player; } // 調用接收對象(錄音機)的 rewind() 方法 public void execute() { player.rewind(); } } |
/** * 錄音機暫停命令 * 具體命令角色類 * */ public class StopCommond implements Commond{ AudioPlayer player; public StopCommond(AudioPlayer player) { this.player = player; } // 調用接收對象(錄音機)的 stop() 方法 public void execute() { player.stop(); } } |
/** * 鍵盤類 * 請求者角色 * */ public class Keypad { private Commond play; private Commond stop; private Commond rewind; public void setPlayCommond(Commond play) { this.play = play; } public void setStopCommond(Commond stop) { this.stop = stop; } public void setRewindCommond(Commond rewind) { this.rewind = rewind; } // 執行播放方法 public void play() { play.execute(); } // 執行暫停方法 public void stop() { stop.execute(); } // 執行倒帶方法 public void rewind() { rewind.execute(); } } |
/** * 具體人--萊斯利 * 客戶端角色 * */ public class Leslie { public static void main(String[] args) { // 創建接受者對象,即收音機對象 AudioPlayer player = new AudioPlayer(); // 創建命令者對象 Commond play = new PlayCommond(player); Commond stop = new StopCommond(player); Commond rewind = new RewindCommond(player); // 創建請求者對象,即鍵盤對象 Keypad keypad = new Keypad(); keypad.setPlayCommond(play); keypad.setStopCommond(stop); keypad.setRewindCommond(rewind); // 播放 keypad.play(); // 暫停 keypad.stop(); // 倒帶 keypad.rewind(); } } |
/** * 定義巨集命令介面 * */ public interface MacroCommand extends Command{ /** * 巨集命令存儲的管理方法 * 可以添加一個成員命令 */ public void add(Command cmd); /** * 巨集命令存儲的管理方法 * 可以刪除一個成員命令 */ public void remove(Command cmd); } |
/** * 具體的巨集命令,對存儲的若幹命令進行操作 * */ public class MacroAudioCommand implements MacroCommand{ // 巨集命令集合 private List<Command> cmdList = new ArrayList<Command>(); // 一次性執行巨集命令集合中的各命令 public void execute() { System.out.println("-------自動回放保存的命令-------"); for(Command cmd : cmdList) { cmd.execute(); } System.out.println("------------回放完畢------------"); } public void add(Command cmd) { cmdList.add(cmd); } public void remove(Command cmd) { cmdList.remove(cmd); } } |
/** * 具體人--萊斯利 * 客戶端角色 * */ public class Leslie { public static void main(String[] args) { // 創建接受者對象,即收音機對象 AudioPlayer player = new AudioPlayer(); // 創建命令者對象 Command play = new PlayCommond(player); Command stop = new StopCommond(player); Command rewind = new RewindCommond(player); MacroCommand macro = new MacroAudioCommand(); macro.add(play); macro.add(rewind); macro.add(stop); macro.execute(); } } |