什么是命令模式
命令模式Command Pattern 是一種行為型設計模式,它把請求封裝成對象,從而將請求的發送者與執行者完全解耦,支持排隊、撤銷、日志記錄等操作。。
模式目標:
解耦命令的發出者(Invoker)與執行者(Receiver)
模式例子
在生活中,比如麥當勞點餐流程,來看看命令模式的經典現實例子:
角色 | 對應命令模式中的角色 |
---|---|
顧客 | 請求發送者 Invoker |
點餐員 | 命令對象 Command |
廚房/廚師 | 實際執行者 Receiver |
點菜單 | 被封裝的命令 Request |
顧客(Invoker)下單 → 服務員記錄訂單(Command) → 廚師(Receiver)執行烹飪操作
- 顧客不關心怎么做菜;
- 廚師不關心是誰點的;
- 服務員中轉命令,負責排隊、取消、記錄等操作。
👉 服務員就是命令模式中的 Command 對象
UML圖
通用表示:
針對本例:
Java 命令模式完整實現
我們模擬一個遙控器控制家電的命令模式案例。
命令接口
Command
public interface OrderCommand {void execute();
}
廚師類(實際執行者 Receiver)
public class Chef {public void makeBurger() {System.out.println("🍔 廚師正在制作漢堡!");}public void makeFries() {System.out.println("🍟 廚師正在炸薯條!");}
}
實際執行者 Receiver
public class BurgerOrder implements OrderCommand {private Chef chef;public BurgerOrder(Chef chef) {this.chef = chef;}@Overridepublic void execute() {chef.makeBurger();}
}public class FriesOrder implements OrderCommand {private Chef chef;public FriesOrder(Chef chef) {this.chef = chef;}@Overridepublic void execute() {chef.makeFries();}
}
服務員類(Invoker)
public class Waiter {private List<OrderCommand> orderList = new ArrayList<>();public void takeOrder(OrderCommand command) {orderList.add(command);}public void submitOrders() {System.out.println("🧾 服務員提交訂單給廚房...");for (OrderCommand command : orderList) {command.execute();}orderList.clear();}
}
客戶端測試代碼
public class Customer {public static void main(String[] args) {Chef chef = new Chef();// 創建命令對象OrderCommand burger = new BurgerOrder(chef);OrderCommand fries = new FriesOrder(chef);// 顧客下單,服務員記錄Waiter waiter = new Waiter();waiter.takeOrder(burger);waiter.takeOrder(fries);// 服務員提交訂單,廚師開始執行waiter.submitOrders();}
}
運行結果
命令模式的優點與用途
優點
優點 | 描述 |
---|---|
解耦調用者和接收者 | 請求發送者不關心具體怎么做 |
支持撤銷與日志記錄 | 可記錄命令序列,回滾操作 |
支持命令組合與排隊 | 命令對象可以存入隊列或組合 |
實際應用場景
應用場景 | 示例說明 |
---|---|
UI按鈕命令綁定 | Swing按鈕點擊執行某個命令 |
事務操作/回滾 | 數據庫事務日志 |
宏命令/組合操作 | Photoshop一鍵動作 |
消息隊列處理 | Kafka、RabbitMQ 消息處理器 |
總結
- 命令模式是高內聚、低耦合的典范;
- 適合對請求進行記錄、排隊、撤銷等處理;
- 可廣泛應用于 UI 控件回調、遙控設備、游戲命令、數據庫事務管理等場景。
參考
《23種設計模式概覽》
附
@startuml
title Java命令模式結構圖interface Command {+execute()
}class ConcreteCommand {-receiver: Receiver+execute()
}class Receiver {+action()
}class Invoker {+setCommand(cmd: Command)+invoke()
}Command <|-- ConcreteCommand
ConcreteCommand --> Receiver
Invoker --> Command@enduml