設計模式 --- 命令模式
阿新 • • 發佈:2018-11-22
1.定義
將一個請求封裝成一個物件,從而讓使用者使用不同的請求把客戶端引數化;對請求排隊或者記錄請求日誌,以及支援可撤銷的操作。
2.使用場景
需要抽象出待執行的動作,然後以引數的形式提供出來,類似於過程設計中的回撥機制。
在不同的時刻指定、排列和執行請求。
需要支援取消操作。
支援修改日誌功能。
需要支援事物操作。
3.簡單實現
以一個電視遙控器功能為例,遙控器能控制電視機的開機、關機、調解音量、切換頻道。
//定義一個接收者角色,真正具體處理邏輯的方法 class TvFunction{ //執行開機 void PowerOn(){ System.out.println("底層呼叫硬體通電...開機"); } //執行關機 void PowerOff(){ System.out.println("底層呼叫硬體斷電...關機"); } //執行頻道切換 void ChangeChannal(){ System.out.println("呼叫底層程式程式碼...切換頻道"); } //執行音量調節 void TurnVoice(){ System.out.println("呼叫底層程式程式碼...調節音量"); } } interface Command{ //命令執行的方法 void execute(); } //開機命令 class PowerOn implements Command{ //持有一個接收者的引用 private TvFunction function; public PowerOn(TvFunction function) { this.function = function; } @Override public void execute() { //呼叫具體的開機方法 function.PowerOn(); } } //關機命令 class PowerOFF implements Command{ //持有一個接收者的引用 private TvFunction function; public PowerOFF(TvFunction function) { this.function = function; } @Override public void execute() { //呼叫具體的關機機方法 function.PowerOff(); } } //頻道切換命令 class Channal implements Command{ //持有一個接收者的引用 private TvFunction function; public Channal(TvFunction function) { this.function = function; } @Override public void execute() { //呼叫具體的切換頻道方法 function.ChangeChannal(); } } //音量調節命令 class Voice implements Command{ //持有一個接收者的引用 private TvFunction function; public Voice(TvFunction function) { this.function = function; } @Override public void execute() { //呼叫具體的音量調節方法 function.TurnVoice(); } } //定義請求者 遙控器 class TvContorllor{ private PowerOn powerOn; //開機物件的引用 private PowerOFF powerOFF; //關機物件的引用 private Channal channal; //頻道切換物件的引用 private Voice voice; //音量調節物件的引用 public void setPowerOn(PowerOn powerOn) { this.powerOn = powerOn; } public void setPowerOFF(PowerOFF powerOFF) { this.powerOFF = powerOFF; } public void setChannal(Channal channal) { this.channal = channal; } public void setVoice(Voice voice) { this.voice = voice; } //開機 public void powerOn(){ powerOn.execute(); } //關機 public void powerOff(){ powerOFF.execute(); } //調解音量 public void turnVoice(){ voice.execute(); } //切換頻道 public void changeChannal(){ channal.execute(); } } public class CommandMode { public static void main(String[] args){ //首先要有電視機的功能 TvFunction function = new TvFunction(); //構造4種命令 PowerOn powerOn = new PowerOn(function); PowerOFF powerOFF = new PowerOFF(function); Channal channal = new Channal(function); Voice voice = new Voice(function); //構造一個遙控器 TvContorllor tvContorllor = new TvContorllor(); tvContorllor.setPowerOn(powerOn); tvContorllor.setPowerOFF(powerOFF); tvContorllor.setChannal(channal); tvContorllor.setVoice(voice); //使用者可以隨便按遙控器控制電視 tvContorllor.powerOn(); tvContorllor.changeChannal(); tvContorllor.turnVoice(); tvContorllor.powerOff(); }
輸出:
呼叫邏輯做的如此複雜,原因是為了程式碼交給別人來維護時,比較清晰,遵循了設計模式重要原則:對修改關閉對拓展開放。此外,還有一個好處是可以再TvContorllor類中儲存執行過的命令,我們可以方便知道執行過哪些命令,還可以恢復。
4.小結
優點:
更弱的耦合性,更靈活的控制性,更好的拓展性;
缺點:
類的膨脹,大量的衍生類