您好,登錄后才能下訂單哦!
設計模式之命令模式-引導篇及原理
引導
司小司又接到了新項目:家電自動化遙控器API項目。
項目背景:隨著物聯網的流行以及智能化家具普及。一個遙控器可以管控家里所有設備(家電等)也很正常了。
來源:凱哥Java(kaigejava)
如上圖:假設空心的是關,實心的是開。
需求:
1:給出各個家電(電燈、電視、音響等)的API,需要在這個遙控器接口中,對接這些API來實現對不同家電的控制。
2:要求自動化遙控器要擴展性好、維護性好。
第一版設計:面向對象的傳統思維
說明:0代表電燈對象,1打開音響的音量命令 2:音響音量命令
我們來看看傳統OO思維下項目結構:
說明:
1:電燈和音響SDK相關的API
2:傳統OO思維下的遙控器
3:遙控器接口
4:測試類
電燈SDKAPI
public class?LightAPI {
? ?/**
? ? * 電燈所在位置
? ? */
? ?private?String?location?=?"";
? ?public?LightAPI (String location){
? ? ? ?this.location?= location;
? ?}
? ?/**
? ? * 開燈效果
? ? */
? ?public void?On(){
? ? ? ?System.out.println(location?+"的燈打開");
? ?}
? ?/**
? ? * 關燈
? ? */
? ?public void?Off(){
? ? ? ?System.out.println(location+"的燈關了");
? ?}
}
遙控器接口:
public interface?Control {
? ?public void?onButton(int?slot);
? ?public void?offButton(int?slot);
? ?public void?undoButton();
}
傳統oo對象實現了遙控器接口:
/**
* Created by kaigejava on 2019/8/28.
* 傳統面向對象的遙控器對象
*
*/
public class?TraditionOOControl?implements?Control {
? ?private?LightAPI?light;
? ?private?StereoAPI?stereo;
? ?public?TraditionOOControl(LightAPI light,StereoAPI stereo){
? ? ? ?this.light?= light;
? ? ? ?this.stereo?= stereo;
? ?}
? ?@Override
? ?public void?onButton(int?slot) {
? ? ? ?switch?(slot) {
? ? ? ? ? ?case?0:
? ? ? ? ? ? ? ?light.On();
? ? ? ? ? ? ? ?break;
? ? ? ? ? ?case?1:
? ? ? ? ? ? ? ?stereo.On();
? ? ? ? ? ? ? ?break;
? ? ? ? ? ?case?2:
? ? ? ? ? ? ? ?int?vol =?stereo.GetVol();
? ? ? ? ? ? ? ?if?(vol <?11) {
? ? ? ? ? ? ? ? ? ?stereo.AddVolume(++vol);
? ? ? ? ? ? ? ?}
? ? ? ? ? ? ? ?break;
? ? ? ?}
? ?}
? ?@Override
? ?public void?offButton(int?slot) {
? ? ? ?switch?(slot) {
? ? ? ? ? ?case?0:
? ? ? ? ? ? ? ?light.Off();
? ? ? ? ? ? ? ?break;
? ? ? ? ? ?case?1:
? ? ? ? ? ? ? ?stereo.Off();
? ? ? ? ? ? ? ?break;
? ? ? ? ? ?case?2:
? ? ? ? ? ? ? ?int?vol =?stereo.GetVol();
? ? ? ? ? ? ? ?if?(vol >?0) {
? ? ? ? ? ? ? ? ? ?stereo.downVolume(--vol);
? ? ? ? ? ? ? ?}
? ? ? ? ? ? ? ?break;
? ? ? ?}
? ?}
? ?@Override
? ?public void?undoButton() {
? ?}
}
測試類:
public class?OOTest {
? ?public static void?main(String[] args) {
? ? ? ?Control ctl;
? ? ? ?LightAPI light =?new?LightAPI("臥室");
? ? ? ?StereoAPI stereo =?new?StereoAPI();
? ? ? ?ctl =?new?TraditionOOControl(light, stereo);
? ? ? ?ctl.onButton(0);
? ? ? ?ctl.offButton(0);
? ? ? ?ctl.onButton(1);
? ? ? ?ctl.onButton(2);
? ? ? ?ctl.offButton(2);
? ? ? ?ctl.offButton(1);
? ?}
}
運行結果:
這樣來看,貌似可以了。我們在來看看這樣做又什么不好。
假設現在又有了新需求,需要對接一個掃地機器人(相信大家知道,現在掃地機器人很多家庭都在用了吧)。這個需求來了,我們應該怎么做呢 ?
需要修改的地方:
1:SDK肯定需要新增加機器人對于的類
2:我們在TraditionControl類中也需要添加機器人的屬性,并且在有參構造函數、OnButton方法OffButton方法中都有做對應的調整。
感覺真個TraditionControl對象都被修改了。這樣還只是添加了一個。如果再過兩天又需要添加一個智能音響或者其他的。同樣的修改還需要再來一遍。這樣雖然功能是能實現,但是再擴展性和維護性上就不好了。就不符合人家客戶的需求了。
綜上所述,司小司決定不使用傳統的OO思想來實現了。
我們來分析,SDK和遙控器之間,是通過一個一個按鈕(命令)進行連接了。那么,有沒有一種更好的方案來實現呢?司小司經過調研發現,命令模式就很適合這種場景了。
我們來看看命令模式。
命令模式原理
我們先來看看命令模式原理類圖,如下圖:
原理類圖說明:
控制器(Invoker)里面有個命令接口(Command),通過控制器里面的命令接口調用實現該接口的類(ConcreteCommand),進而來控制,具體對象(Receiver)執行
命令模式:
簡單理解:就是將我們的命令抽取成一個對象,然后將這個對象放到我們控制器里面。通過控制器來調用命令對象的實際方法。
定義:
將請求、命令、動作等封裝成對象,這樣可以讓項目使用這些對象參數化其他對象。進而達到命令的請求者和執行者進行解耦。
在知道命令模式原理之后,我們再來重新設計遙控器項目的類圖,就如下了:
類圖說明:
Control:遙控器對象
Command:命令接口
LigthXXX:電燈對象相關命令對象
StereoXXX:音響對象相關命令對象
Light:電燈對象
Stereo:音響對象
好了,我們經過分析,使用命令模式對項目進行了設計。那么接下來,我們就使用代碼來實現吧。歡迎接著學習下一篇。再下一篇中,我們將通過代碼來實現命令模式下的遙控器項目。
凱哥個人博客:www.kaigejava.com
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。