命令模式是對命令的封裝,每個命令都是一個操做:請求方發出請求要求執行一個操做;接收方收到請求,並執行操做。命令模式解耦了請求方shell
和接收方,請求方只需請求執行命令,不用關心命令怎麼被接收、怎樣操做以及是否被執行等。命令模式屬於行爲型設計模式。設計模式
在軟件系統中,行爲請求者與行爲實現者一般是一種緊耦合關係,由於這樣的實現簡單明瞭。但緊耦合關係缺少擴展性,在某些場合中,須要對行爲架構
進行記錄、撤銷或者重作等處理時,只能修改源碼。而命令模式經過在請求與實現之間引入一個抽象命令接口。解耦了請求與實現,而且中間件是抽象的,測試
它由不一樣的子類實現,所以具備擴展性。因此,命令模式的本質是解耦命令請求與處理。this
從上圖能夠看出,命令模式主要包含4個角色。spa
從命令模式的UML類圖中,能夠很清晰地看出,ICommand的出現就是做爲Receiver和Invoker的中間件,解耦了彼此。命令行
假如咱們開發一個播放器,播放器播放功能、拖動進度條功能、中止播放功能、暫停功能,咱們在操做播發器的時候並不知道之間調用播放器設計
哪一個功能,而是經過一個控制傳達去傳遞指令給播放器內核,具體傳達什麼指令,會被封裝成一個個按鈕。那麼每一個按鈕就至關於一條命令的封裝。日誌
用控制條實現了用戶發送指令與播放器內核接收指令的解耦。下面來看代碼,首先建立播放器內核類:code
public class GPlayer { public void play() { System.out.println("正常播放"); } public void speed() { System.out.println("拖動進度條"); } public void stop() { System.out.println("中止播放"); } public void pause() { System.out.println("暫停播放"); } }
建立命令接口:
public interface IAction { void execute(); }
建立播放指令類:
public class PlayAction implements IAction { private GPlayer gplayer; public PlayAction(GPlayer gplayer) { this.gplayer = gplayer; } public void execute() { gplayer.play(); } }
建立暫停指令類:
public class PauseAction implements IAction { private GPlayer gplayer; public PauseAction(GPlayer gplayer) { this.gplayer = gplayer; } public void execute() { gplayer.pause(); } }
建立拖動進度條類:
public class SpeedAction implements IAction { private GPlayer gplayer; public SpeedAction(GPlayer gplayer) { this.gplayer = gplayer; } public void execute() { gplayer.speed(); } }
建立中止播放指令:
public class StopAction implements IAction { private GPlayer gplayer; public StopAction(GPlayer gplayer) { this.gplayer = gplayer; } public void execute() { gplayer.stop(); } }
建立控制條controller類:
public class Controller { private List<IAction> actions = new ArrayList<IAction>(); public void addAction(IAction action) { actions.add(action); } public void execute(IAction action) { action.execute(); } public void executes() { for (IAction action : actions) { action.execute(); } actions.clear(); } }
從上面代碼來看,控制條能夠執行單條命令,也能夠批量執行多條命令。下面看客戶端的測試代碼:
public class Test { public static void main(String[] args) { GPlayer player = new GPlayer(); Controller controller = new Controller(); controller.execute(new PlayAction(player)); controller.addAction(new PauseAction(player)); controller.addAction(new PlayAction(player)); controller.addAction(new StopAction(player)); controller.addAction(new SpeedAction(player)); controller.executes(); } }
因爲控制條已經與播放器內核解耦了,之後若是想擴展新命令,只須要增長命令便可,控制條的結構無須改動。