摘要:好的,我重新繪制了一張圖反映命令模式如下圖,流程與上圖相同。感謝你看到這里,命令模式的上部分到這里就結(jié)束了,本人文筆隨便,若有不足或錯(cuò)誤之處望給予指點(diǎn),度彎腰很快我會(huì)發(fā)布命令模式下的內(nèi)容,生命不息,編程不止參考書籍設(shè)計(jì)模式
封裝調(diào)用:將方法調(diào)用給封裝起來。
這次講的是命令模式,他的作用就是方法給封裝起來,有需要的時(shí)候就調(diào)用,調(diào)用者并不需要關(guān)心它是如何實(shí)現(xiàn)的。
我們來看一張流程圖
注:
1、訂單封裝了準(zhǔn)備餐點(diǎn)的請(qǐng)求,
2、女服務(wù)員的工作是接受訂單,然后調(diào)用訂單的orderUp方法,女服務(wù)員并不關(guān)心訂單內(nèi)容是什么,她只需調(diào)用orderUp方法
3、廚師就是一個(gè)對(duì)象,他是真正知道餐點(diǎn)的具體內(nèi)容的人,一旦女服務(wù)員調(diào)用orderUp方法,廚師就接手,實(shí)現(xiàn)餐點(diǎn)的具體方法,這里廚師和女服務(wù)員是解耦的,訂單封裝了餐點(diǎn)的細(xì)節(jié),她只要調(diào)用每個(gè)訂單的方法即可,而廚師看了訂單就知道該做些什么餐點(diǎn)。
好的,我重新繪制了一張圖反映命令模式如下圖,流程與上圖相同。
OK,我們基本了解了命令模式的流程怎樣
下面寫一個(gè)模擬遙控器打開電燈和門這么個(gè)動(dòng)作的Demo例子
1、寫電燈和門的類
電燈
package Entity; public class Light { public Light() { } public void on() { System.out.println("燈亮了"); } public void off() { System.out.println("燈滅了"); } }
門
package Entity; public class Door { public Door() { } public void OpenDoor() { System.out.println("門開了"); } public void OffDoor() { System.out.println("門關(guān)了"); } public void StopDoor(){ System.out.println("門停止了"); } public void DoorLightOn(){ System.out.println("門里的燈亮了"); } }
2、創(chuàng)建命令接口
package Interface; /** * 命令接口 * * @author Joy * */ public interface Command { // 命令執(zhí)行方法 public void execute(); }
3、實(shí)現(xiàn)一個(gè)打開電燈的命令
package Implements; import Entity.Light; import Interface.Command; public class LightOnCommand implements Command { Light light; // 構(gòu)造器中傳入某個(gè)電燈類型 // 以便讓這個(gè)命令控制,然后記錄在light實(shí)例變量中, // 當(dāng)調(diào)用execute時(shí),light會(huì)根據(jù)類型不同執(zhí)行不同燈亮方法 public LightOnCommand(Light light) { this.light = light; } // 執(zhí)行燈亮方法 @Override public void execute() { light.on(); } }
門的實(shí)現(xiàn)方法
package Implements; import Entity.Door; import Interface.Command; public class DoorOpenCommand implements Command { Door door; public DoorOpenCommand(Door door) { this.door = door; } @Override public void execute() { door.OpenDoor(); } }
4、調(diào)用命令對(duì)象(遙控器)
package Control; import Interface.Command; /** * 簡(jiǎn)單遙控器 *相當(dāng)于調(diào)用者 * @author Joy * */ public class SimpleRemoteControl { // 命令對(duì)象類型,相當(dāng)于插槽控制著一個(gè)裝置 Command slot; public SimpleRemoteControl() { } // 這個(gè)方法用來設(shè)置插槽控制的命令 // 如果客戶需要改變遙控器按鈕的行為,可以多次調(diào)用此方法 public void setCommand(Command command) { slot = command; } // 執(zhí)行方法 public void buttonWasPressed() { slot.execute(); } }
5、測(cè)試類(使用遙控器)
package TestMain; import Control.SimpleRemoteControl; import Entity.Door; import Entity.Light; import Implements.DoorOpenCommand; import Implements.LightOnCommand; public class LightTestMain { public static void main(String[] args) { // 遙控器相當(dāng)于命令的調(diào)用者,會(huì)傳入一個(gè)命令對(duì)象,可以用來發(fā)送請(qǐng)求 SimpleRemoteControl remote = new SimpleRemoteControl(); // 創(chuàng)建一個(gè)電燈對(duì)象,此對(duì)象也就是請(qǐng)求中的接收者 Light light = new Light(); Door door = new Door(); // 創(chuàng)建打開電燈動(dòng)作的類,并傳入接收者(light) LightOnCommand lightOn = new LightOnCommand(light); DoorOpenCommand doorOpen = new DoorOpenCommand(door); // 命令傳給調(diào)用者(遙控器) remote.setCommand(lightOn); // 模擬按下按鈕 remote.buttonWasPressed(); remote.setCommand(doorOpen); remote.buttonWasPressed(); } }
效果圖
這就是個(gè)基本命令模式的使用算是牛刀小試了一下,
命令模式定義:將“請(qǐng)求”封裝成對(duì)象,以便使用不同的請(qǐng)求、隊(duì)列或者日志 來參數(shù)化其他對(duì)象,命令模式也支持可撤銷的操作。
下面是這模式的類圖
接下來繼續(xù)模擬一個(gè)遙控器,只不過這次需求變得復(fù)雜了起來。
示例圖如下,
每個(gè)遙控器的插槽都對(duì)應(yīng)一個(gè)命令嗎,這樣遙控器就變?yōu)榱恕罢{(diào)用者”,當(dāng)按下按鈕,對(duì)應(yīng)的命令對(duì)象的execute方法就會(huì)被調(diào)用,結(jié)果就是接收者(例如:電燈,天花板電扇,音響)的動(dòng)作被調(diào)用。
代碼開始
1、實(shí)體類
電燈
package Entity; public class Light { //所處位置 String location; public Light(String location) { this.location = location; } public void on(){ System.out.println(location+"燈亮了"); } public void off(){ System.out.println(location+"燈關(guān)了"); } }
音響
package Entity; /** * 音響類 * * @author Joy * */ public class Stereo { //location 一個(gè)地點(diǎn)變量 String location; public Stereo(String location) { this.location = location; } public void on(){ System.out.println(location+"音響啟動(dòng)"); } public void off(){ System.out.println(location+"音響關(guān)閉"); } public void setDVD(){ System.out.println(location+"音響放一張DVD并播放"); } public void setCD(){ System.out.println(location+"音響放一張CD并播放"); } public void setRadio(){ System.out.println(location+"音響以收音機(jī)無線電形式播放"); } public void setVolume(int volume) { System.out.println(location + " 音響音量設(shè)置為 " + volume); } }
電視
package Entity; public class TV { String location; int channel;//電視頻道 public TV(String location) { this.location = location; } public void TVOn(){ System.out.println(location+"電視自動(dòng)打開了"); } public void TVOff(){ System.out.println(location+"電視自動(dòng)關(guān)閉了"); } //電視調(diào)頻道 public void setTVChannel(int channel){ this.channel=channel; System.out.println(location+"電視自動(dòng)調(diào)到"+channel+"頻道"); } }
2、創(chuàng)建命令接口對(duì)象
package Interface; public interface Command { //執(zhí)行 public void execute(); //撤銷 public void undo(); }
3、實(shí)現(xiàn)遙控器類(調(diào)用者)
package Control; import Implements.NoCommand; import Interface.Command; /** * 實(shí)現(xiàn)遙控器 * * @author Joy */ public class RemoteControl { // 此時(shí)遙控器要處理7個(gè)開關(guān)控制,使用數(shù)組 Command[] onCommands = new Command[7]; Command[] offCommands = new Command[7]; // 撤銷當(dāng)然要先知道之前的命令 // 撤銷變量,用來追蹤最后被調(diào)用的命令 Command undoCommand; // 初始化遙控器類,一開始都是無操作noCommand是一個(gè)無操作對(duì)象 // 在測(cè)試輸出時(shí),沒有被明確指明命令的插槽,其命令默認(rèn)為noCommand對(duì)象 public RemoteControl() { Command noCommand = new NoCommand(); for (int i = 0; i < onCommands.length; i++) { onCommands[i] = noCommand; offCommands[i] = noCommand; } undoCommand = noCommand; } /** * * @param slot * :插槽的位置(類似索引值) * @param onCommand * :開的命令 * @param offCommand * :關(guān)的命令 這些命令被記錄在開關(guān)數(shù)組對(duì)應(yīng)的插槽位置上,以便使用 */ public void setCommand(int slot, Command onCommand, Command offCommand) { onCommands[slot] = onCommand; offCommands[slot] = offCommand; } /** * 開關(guān)按鈕是對(duì)應(yīng)的插槽位置負(fù)責(zé)調(diào)用對(duì)應(yīng)的方法 * 遙控器上面開關(guān)按鈕的不同位置就可以控制不同類型的燈 * undoCommand:當(dāng)按下遙控器按鈕時(shí),我們?nèi)〉眠@個(gè)命令,并記錄在undoCommand里 * @param slot */ public void onButtonWasPushed(int slot) { onCommands[slot].execute(); undoCommand=onCommands[slot]; } public void offButtonWasPushed(int slot) { offCommands[slot].execute(); undoCommand=offCommands[slot]; } //添加一個(gè)撤銷按鈕 public void undoButtonWasPushed(){ //撤銷 undoCommand.undo(); } // 打印每個(gè)插槽和它對(duì)應(yīng)的命令 @Override public String toString() { StringBuffer sbf = new StringBuffer(); sbf.append(" ======================遙控器====================== "); for (int i = 0; i < onCommands.length; i++) { sbf.append("[插槽" + i + "]" + onCommands[i].getClass().getName() + " " + offCommands[i].getClass().getName() + " "); } return sbf.toString(); } }
4、實(shí)現(xiàn)各個(gè)命令(7個(gè))
package Implements; import Entity.Light; import Interface.Command; public class LightOffCommand implements Command { //具體對(duì)象變量 Light light; public LightOffCommand(Light light) { this.light = light; } @Override public void execute() { light.off(); } @Override public void undo() { light.on(); } }
package Implements; import Entity.Light; import Interface.Command; public class LightOnCommand implements Command { // 具體對(duì)象變量 Light light; public LightOnCommand(Light light) { this.light = light; } // 執(zhí)行打開電燈方法 @Override public void execute() { light.on(); } // 撤銷操作,關(guān)閉電燈 @Override public void undo() { light.off(); } }
package Implements; import Interface.Command; public class NoCommand implements Command { // 這是個(gè)無操作類,插槽內(nèi)的類沒有實(shí)例化是就走這個(gè)對(duì)象 @Override public void execute() { } @Override public void undo() { // TODO 自動(dòng)生成的方法存根 } }
package Implements; import Entity.Stereo; import Interface.Command; public class StereoOffCommand implements Command { // 具體對(duì)象變量 Stereo stereo; public StereoOffCommand(Stereo stereo) { this.stereo = stereo; } public void execute() { stereo.off(); } @Override public void undo() { stereo.on(); } }
package Implements; import Entity.Stereo; import Interface.Command; /** * 音響的 * * @author Joy * */ public class StereoOnWithCDCommand implements Command { // 具體對(duì)象變量 Stereo stereo; public StereoOnWithCDCommand(Stereo stereo) { this.stereo = stereo; } // 具體實(shí)現(xiàn)方法(方法再去調(diào)用實(shí)現(xiàn)方法) public void execute() { stereo.on(); stereo.setCD(); stereo.setVolume(11); } @Override public void undo() { stereo.off(); } }
package Implements; import Entity.TV; import Interface.Command; public class TVOffCommand implements Command { TV tv; public TVOffCommand(TV tv) { this.tv = tv; } @Override public void execute() { tv.TVOff(); } @Override public void undo() { tv.TVOn(); } }
package Implements; import Entity.TV; import Interface.Command; public class TVOnCommand implements Command { TV tv; public TVOnCommand(TV tv) { this.tv = tv; } @Override public void execute() { tv.TVOn(); tv.setTVChannel(15); } @Override public void undo() { tv.TVOff(); } }
5、測(cè)試類
package TestMain; import Control.RemoteControl; import Entity.Light; import Entity.Stereo; import Entity.TV; import Implements.LightOffCommand; import Implements.LightOnCommand; import Implements.StereoOffCommand; import Implements.StereoOnWithCDCommand; import Implements.TVOffCommand; import Implements.TVOnCommand; public class TestMain { public static void main(String[] args) { // 實(shí)例化遙控器 RemoteControl remoteControl = new RemoteControl(); // 實(shí)例化需要控制對(duì)象,并傳入房子位置 Stereo stereo = new Stereo("客廳"); Light light = new Light("客廳"); TV tv = new TV("臥室"); // 調(diào)用設(shè)備開關(guān)方法 StereoOnWithCDCommand stereoOnWichCD = new StereoOnWithCDCommand(stereo); StereoOffCommand stereoOffWithCD = new StereoOffCommand(stereo); LightOnCommand lightOn = new LightOnCommand(light); LightOffCommand lightOff = new LightOffCommand(light); TVOnCommand tvOn = new TVOnCommand(tv); TVOffCommand tvOff = new TVOffCommand(tv); // 設(shè)置插槽位置(遙控器的哪個(gè)按鈕對(duì)應(yīng)哪個(gè)設(shè)備開關(guān)) remoteControl.setCommand(0, lightOn, lightOff); remoteControl.setCommand(3, stereoOnWichCD, stereoOffWithCD); remoteControl.setCommand(5, tvOn, tvOff); // 輸出插槽位置 System.out.println(remoteControl); // 按下開關(guān) remoteControl.onButtonWasPushed(0); remoteControl.offButtonWasPushed(0); remoteControl.onButtonWasPushed(3); remoteControl.offButtonWasPushed(3); remoteControl.onButtonWasPushed(5); remoteControl.offButtonWasPushed(5); } }
效果圖
+1~~~~
在這個(gè)實(shí)例當(dāng)中我特意預(yù)留了撤銷的功能,讓我們看看加上撤銷功能(undo)的遙控器是怎么運(yùn)行的把。
新建一個(gè)undoCommandTest類
package TestMain; import Control.RemoteControl; import Entity.Light; import Implements.LightOffCommand; import Implements.LightOnCommand; public class undoCommandTest { public static void main(String[] args) { // 實(shí)例化遙控器 RemoteControl remoteControl = new RemoteControl(); // 實(shí)例化需要控制對(duì)象,并傳入房子位置 Light light = new Light("客廳"); // 調(diào)用設(shè)備開關(guān)方法 LightOnCommand lightOn = new LightOnCommand(light); LightOffCommand lightOff = new LightOffCommand(light); // 設(shè)置插槽位置(遙控器的哪個(gè)按鈕對(duì)應(yīng)哪個(gè)設(shè)備開關(guān)) remoteControl.setCommand(0, lightOn, lightOff); // 按下開關(guān) remoteControl.onButtonWasPushed(0); remoteControl.offButtonWasPushed(0); // 輸出插槽位置 System.out.println(remoteControl); // 撤銷 System.out.println("按下撤銷按鈕"); remoteControl.undoButtonWasPushed(); System.out.println(""); remoteControl.offButtonWasPushed(0); remoteControl.onButtonWasPushed(0); System.out.println(remoteControl); System.out.println("按下撤銷按鈕"); remoteControl.undoButtonWasPushed(); } }
效果圖
看來撤銷的功能也OK,我腦中甚至浮現(xiàn)出在JavaWeb里這個(gè)撤銷的效果了,23333。
感謝你看到這里,命令模式的上部分到這里就結(jié)束了,本人文筆隨便,若有不足或錯(cuò)誤之處望給予指點(diǎn),90度彎腰~~~很快我會(huì)發(fā)布命令模式下的內(nèi)容,生命不息,編程不止!
參考書籍:《Head First 設(shè)計(jì)模式》
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://specialneedsforspecialkids.com/yun/70336.html
摘要:要點(diǎn)命令模式將發(fā)出請(qǐng)求的對(duì)象和執(zhí)行請(qǐng)求的對(duì)象解耦。感謝你看到這里,命令模式到這里就結(jié)束了,本人文筆隨便,若有不足或錯(cuò)誤之處望給予指點(diǎn),度彎腰很快我會(huì)發(fā)布下一個(gè)設(shè)計(jì)模式的內(nèi)容,生命不息,編程不止 繼續(xù)上部分的說 在之前的文章最后寫了一個(gè)帶有撤銷電燈功能的遙控器功能,通常,想要實(shí)現(xiàn)撤銷的功能,需要記錄撤銷之前的狀態(tài)是什么,就比方說電扇,允許有多個(gè)風(fēng)速狀態(tài),也允許被關(guān)閉。直接上代碼。 1、風(fēng)...
摘要:郵件激活后,可以測(cè)試登錄這條命令會(huì)完成登錄,并將認(rèn)證信息報(bào)錯(cuò)起來供后面使用。所以先用命令退出容器,再運(yùn)行命令命令中,指定了要提交的修改過的容器的目標(biāo)鏡像倉(cāng)庫(kù)鏡像名。提交的知識(shí)創(chuàng)建容器的鏡像與容器的當(dāng)前狀態(tài)之間的差異部分,很輕量。 假期快要結(jié)束了,干點(diǎn)正事,接著Docker的學(xué)習(xí)。 構(gòu)建鏡像 構(gòu)建鏡像的兩種方法: 使用docker commit 命令 使用docker build...
摘要:結(jié)構(gòu)型模式適配器模式橋接模式裝飾模式組合模式外觀模式享元模式代理模式。行為型模式模版方法模式命令模式迭代器模式觀察者模式中介者模式備忘錄模式解釋器模式模式狀態(tài)模式策略模式職責(zé)鏈模式責(zé)任鏈模式訪問者模式。 主要版本 更新時(shí)間 備注 v1.0 2015-08-01 首次發(fā)布 v1.1 2018-03-12 增加新技術(shù)知識(shí)、完善知識(shí)體系 v2.0 2019-02-19 結(jié)構(gòu)...
閱讀 2432·2021-11-22 13:53
閱讀 1126·2021-09-22 16:06
閱讀 1370·2021-09-02 15:21
閱讀 1895·2019-08-30 15:55
閱讀 3116·2019-08-29 11:19
閱讀 1911·2019-08-26 13:23
閱讀 931·2019-08-23 18:23
閱讀 1748·2019-08-23 16:06