設計模式之命令模式(三)

我回來啦!今天是週六,一看命令模式還有一個總結未完成,趕忙爬起來作作好。編程

就如上一篇所說的,若是擁有了一個遙控器,卻沒法光憑按下一個按你,就同時能弄暗燈光、打開音響和電視、設置到DVD,並讓熱水器開始加溫,那麼我要這個遙控器還有什麼意義呢?數組

使用宏命令

根據比較高級的想法來看,就是咱們須要製造一種新的命令,用來執行其餘一堆命令,而不僅是執行一個命令,這樣就是一個不錯的想法了吧。這就是咱們將要說的宏命令。網絡

public class MacroCommand implements Command {
    // 在宏命令中,用命令數組存儲一大堆命令
	Command[] commands;
 
	public MacroCommand(Command[] commands) {
		this.commands = commands;
	}
 
	public void execute() {
		for (int i = 0; i < commands.length; i++) {
		// 當這個宏命令被遙控器執行時,就一次性執行數組裏的每一個命令
			commands[i].execute();
		}
	}
 
    /** * NOTE: these commands have to be done backwards to ensure * proper undo functionality */
	public void undo() {
		for (int i = commands.length -1; i >= 0; i--) {
			commands[i].undo();
		}
	}
}

複製代碼

讓咱們來看下如何使用宏命令:數據結構

  1. 先建立想要進入宏的命令集合
Light light = new Light("Living Room");
TV tv = new TV("Living Room");
Stereo stereo = new Stereo("Living Room");
Hottub hottub = new Hottub();
 
LightOnCommand lightOn = new LightOnCommand(light);
StereoOnCommand stereoOn = new StereoOnCommand(stereo);
TVOnCommand tvOn = new TVOnCommand(tv);
HottubOnCommand hottubOn = new HottubOnCommand(hottub);
複製代碼
  1. 接下來建立兩個數組,其中一個用來記錄開啓命令,另外一個用來記錄關閉命令,並在數組內放入對應的命令
Command[] partyOn = { lightOn, stereoOn, tvOn, hottubOn};
Command[] partyOff = { lightOff, stereoOff, tvOff, hottubOff};
  
MacroCommand partyOnMacro = new MacroCommand(partyOn);
MacroCommand partyOffMacro = new MacroCommand(partyOff);
複製代碼
  1. 而後將宏命令指定給咱們所但願的按鈕:
remoteControl.setCommand(0, partyOnMacro, partyOffMacro);
複製代碼
  1. 最後,只需按下一些按鈕,測試是否正常工做
System.out.println(remoteControl);
System.out.println("--- Pushing Macro On---");
remoteControl.onButtonWasPushed(0);
System.out.println("--- Pushing Macro Off---");
remoteControl.offButtonWasPushed(0);
複製代碼

不會忘記咱們的撤銷功能框架

public void undo() {
	for (int i = commands.length -1; i >= 0; i--) {
		commands[i].undo();
	}
}
複製代碼

命令模式的更多用途:隊列請求

命令能夠將運算塊打包(一個接收者和一組動做),而後將它傳來傳去,就像是通常的對象同樣。如今,即便在命令被建立許久以後,運算依然能夠被調用。事實上,它甚至能夠在不一樣的線程中被調用。咱們能夠利用這樣的特性衍生一些應用,例如:日程安排、線程池、工做隊列等。工具

想象一個工做隊列:你再某一端添加命令,而後另外一端則是線程。線程進行下面的動做:從隊列中取出一個命令,調用它的execute()方法,等待這個調用完成,而後將此命令對象丟棄,再取出下一個命令。。。學習

請注意,工做隊列類和進行計算的對象之間徹底是解耦的。此刻線程可能在進行財務運算,下一刻卻在讀取網絡數據。工做隊列對象不在意到底作些什麼,他們只知道取出命令對象,而後調用其execute()方法。測試

命令模式的更多用途:日誌請求

某些應用須要咱們將全部的動做都記錄在日誌中,並能在系統死機以後,從新調用這些動做恢復到以前的狀態。命令模式可以支持這一點。this

當咱們執行命令的時候,將歷史記錄存儲在磁盤中,一旦系統死機,咱們就能夠將命令對象從新加載,併成批地依次調用這些對象的execute()方法。spa

好比有許多調用大型數據結構的應用沒法在每次改變發生時被快速地存儲。經過使用記錄日誌,咱們能夠將上次檢查點以後的全部操做記錄下來,若是系統出情況,從檢查點開始應用這些操做。好比說,對於電子表格應用,咱們可能想要實現的錯誤回覆方式是將電子表格的操做記錄在日誌中,而不是每次電子表格一有變化就記錄整個電子表格。

對於更高級的應用而言,這些技巧能夠被擴展應用到事務處理中,也就是說,一整羣操做必須所有進行完成,或者沒有進行任何的操做

設計箱內的工具

仍是按照以前的套路,總結下工具箱內新增的工具吧

  • OO基礎

    抽象、封裝、繼承、多態

  • OO原則

    封裝變化

    多用組合,少用繼承

    針對接口編程,不針對實現編程

    爲交互對象之間的鬆耦合設計而努力

    依賴抽象,不要依賴具體類

    類應該對擴展開放,對修改關閉

  • OO模式

    『策略模式』、『觀察者模式』、『裝飾者模式』、『抽象工廠模式』、『工廠方法模式』、『單例模式』

    命令模式』將請求封裝成對象,這可讓你使用不一樣的請求、隊列,或者日誌請求來參數化其餘對象。命令模式也能夠支持撤銷操做。

咱們學習命令模式,就是一個按部就班的過程,先從簡單的開關開始,而後再到複雜的開啓狀態,進而想到隊列,想到記錄日誌這種事務操做。學習也是一個按部就班的過程,咱們經過簡單的Demo學習,而後到項目實踐,再到後面獨立設計框架,我相信你們都能悟出這個道理來。

持續學習,精進學習,咱們會一塊兒加油。下一次,咱們將學習適配器模式與外觀模式

愛生活,愛學習,愛感悟,愛挨踢

相關文章
相關標籤/搜索