目錄
1、介紹
1.1、命令模式定義
1.2、對比
1.3、典型應用場景
2、命令模式的結構
2.1、組成部分:
2.2、整體流程
3、實現
3.1、沒有命令模式
3.2、命令模式寫法
4、命令模式的優缺點
前言
java設計模式分類:
1、介紹
1.1、命令模式定義
?????命令模式(Command Pattern)是一種行為型設計模式,又叫動作模式或事務模式。
????????它將請求(命令)封裝成對象,使得可以用不同的請求對客戶端進行參數化,具體的請求可以在運行時更改、排隊或記錄,它將發出者和接收者解耦(順序:發出者-->命令-->接收者)。
總結:
????????把請求的動作和請求的接收者進行解耦,讓你能將動作封裝成對象,再傳遞、存儲、撤銷或排隊等。
1.2、對比
狀態模式:
Context(電梯)-- 持有當前狀態 --> State(狀態接口)-- 實現 --> OpenState, RunState等
命令模式:
1.3、典型應用場景
1、Runnable接口:
????????Java中的Runnable接口就是一個典型的命令模式的應用。Runnable接口封裝了需要執行的任務,然后可以交給線程去執行。
2、Timer和TimerTask類:
????????這兩個類用于定時任務調度,TimerTask類封裝了要執行的任務,然后由Timer類作為調用者執行這些任務。
3、Statement接口:
????????在Java中與數據庫交互時,SQL語句被封裝成Statement對象,然后由數據庫驅動程序執行相應的命令。
生活示例:
1、 餐廳點餐:
????????在一家餐廳中,服務員充當調用者,廚師充當接收者,菜品可以作為具體命令。當顧客想點菜時,服務員會將顧客的需求封裝成一個命令對象,并傳遞給廚師。廚師根據命令對象中的信息來完成相應的烹飪工作。這樣,顧客和廚師之間不需要直接溝通,而是通過命令對象來實現點餐和烹飪的解耦。
2、遙控器控制家電:
????????拿電視遙控器舉例,遙控器是調用者,電視是接收者。每個按鍵都可以看作是一個具體命令,例如音量加、音量減、切換頻道等。
????????當用戶按下某個按鍵時,遙控器會發送相應的命令給電視,然后電視根據命令執行相應的操作,如增加音量、減小音量或切換頻道。
2、命令模式的結構
2.1、組成部分:
- Command(命令接口/抽象類):?聲明
execute()
方法。 - ConcreteCommand(具體命令):?實現
Command
,并持有Receiver
引用,把請求操作的接收者封裝進來,調用接收者的方法。 - Receiver(接收者):?真正執行業務邏輯的對象。
- Invoker(調用者):?有個成員變量保存Command,并執行
command.execute()
。 - Client(客戶端):?組裝命令、接收者、并給調用者下令。
2.2、整體流程
所有的“做某件事”,都變成訂單(命令對象),Waiter只“發訂單”,Chef只“實現訂單”:
如下圖所示:
????????命令模式,把“執行動作”的代碼封裝成對象。Waiter(服務員)不需要知道每個命令詳情,只要保存一份“命令單子”,然后調用它的執行方法即可。
3、實現
假設你在飯店點菜。
- 你(Client 客戶端):我要點“宮保雞丁”。
- 服務員(Invoker 調用者):拿到菜單,把點菜單(訂單)交給廚房。
- 訂單(Command 命令對象):訂單上寫著“做宮保雞丁”。
- 廚師(Receiver 接收者):收到訂單,立刻開始炒菜。
這樣,服務員并不需要會做菜,他只要拿訂單就行了。
3.1、沒有命令模式
你直接告訴服務員 “去讓張師傅做宮保雞丁”:
代碼如下所示:
// 直接耦合
public class Waiter {private Chef chef = new Chef();public void orderGongBaoChicken() {chef.makeGongBaoChicken();}
}public class Chef {public void makeGongBaoChicken() {System.out.println("炒宮保雞丁!");}
}
// 調用
Waiter waiter = new Waiter();
waiter.orderGongBaoChicken();
3.2、命令模式寫法
1. 命令接口
public interface Command {void execute(); // 執行命令void undo(); // 撤銷命令(可選)
}
- 這里的
Command
相當于“點菜單的模板”,所有的點菜單都要有一個execute方法。
2. 接收者(Receiver)——廚師
public class Chef {public void makeGongBaoChicken() {System.out.println("廚師:炒宮保雞丁!");}public void makeFriedRice() {System.out.println("廚師:炒蛋炒飯!");}
}
- Chef能夠真的炒不同的菜。
3. 具體命令(ConcreteCommand)——不同的訂單
public class GongBaoChickenCommand implements Command {private Chef chef;public GongBaoChickenCommand(Chef chef) {this.chef = chef;}@Overridepublic void execute() {chef.makeGongBaoChicken();}@Overridepublic void undo() {System.out.println("取消宮保雞丁!");}
}public class FriedRiceCommand implements Command {private Chef chef;public FriedRiceCommand(Chef chef) {this.chef = chef;}@Overridepublic void execute() {chef.makeFriedRice();}@Overridepublic void undo() {System.out.println("取消蛋炒飯!");}
}
- 每個命令就是一張“點菜單”,知道自己要交給哪個廚師(Receiver)。
4、調用者(Invoker)服務員
public class Waiter {private Command command;public void setCommand(Command command) {this.command = command;}public void placeOrder() {// 點菜command.execute();}public void cancelOrder() {// 撤銷點菜command.undo();}
}
5、客戶端組裝
public class Customer {public static void main(String[] args) {Chef chef = new Chef();Command gongBaoChicken = new GongBaoChickenCommand(chef);Command friedRice = new FriedRiceCommand(chef);Waiter waiter = new Waiter();// 點宮保雞丁waiter.setCommand(gongBaoChicken);waiter.placeOrder();// 點蛋炒飯waiter.setCommand(friedRice);waiter.placeOrder();// 撤銷剛才的蛋炒飯waiter.cancelOrder();}
}
輸出:
廚師:炒宮保雞丁!
廚師:炒蛋炒飯!
取消蛋炒飯!
有上述示例可知命令模式的功能:
- 解耦:Waiter只需要認識命令Command,不用知道Chef做什么。
- 追加功能:要新增一道菜,只要做一個新的Command類即可,Waiter不用改。
- 支持隊列、日志、撤銷:命令對象能被存儲、排隊,可以撤銷。
4、命令模式的優缺點
1、優點:
徹底解耦“請求者”與“執行者”,調用者無需知道接收者是啥。
請求可以參數化(每個對象帶不同接收者和參數)。
請求可以放隊列、做日志,如事務撤銷與恢復、任務隊列。
增加新命令類非常方便。
2、缺點:
類的數量可能會增多(每種命令都要實現 Command 接口)。
總結
????????命令模式適用于需要將請求封裝成對象,實現請求發出者和接收者之間的解耦,并支持撤銷、隊列化和延遲執行的場景。它雖然可以提高系統的可擴展性和靈活性,但是需要權衡額外的開銷和復雜性。
參考文章:
1、設計模式第19講——命令模式(Command)-CSDN博客文章瀏覽閱讀1.1w次,點贊38次,收藏174次。命令模式是一種行為設計模式,它將請求封裝為對象,使發出者和接收者解耦。文章介紹了命令模式的角色(抽象命令、具體命令、接收者和調用者),優缺點以及在餐廳點餐和Java場景中的應用,還提供了代碼實現示例。https://blog.csdn.net/weixin_45433817/article/details/131465270?ops_request_misc=%257B%2522request%255Fid%2522%253A%2522d919eba72e6dd9b4ef68572ad0a68137%2522%252C%2522scm%2522%253A%252220140713.130102334..%2522%257D&request_id=d919eba72e6dd9b4ef68572ad0a68137&biz_id=0&utm_medium=distribute.pc_search_result.none-task-blog-2~all~top_positive~default-1-131465270-null-null.142^v102^control&utm_term=%E5%91%BD%E4%BB%A4%E6%A8%A1%E5%BC%8F&spm=1018.2226.3001.4187