命令模式
定義
在軟件系統中,“行爲請求者”與“行爲實現者”通常呈現一種“緊耦合”。但在某些場合,比如要對行爲進行“記錄、撤銷/重做、事務”等處理,這種無法抵禦變化的緊耦合是不合適的。在這種情況下,如何將“行爲請求者”與“行爲實現者”解耦?將一組行爲抽象爲對象,實現二者之間的鬆耦合。這就是命令模式(Command Pattern)。1
我們來看下命令模式的定義,明顯的關鍵詞我們都用黑體字標註出來了,行爲的請求者和執行者是關係對象,關鍵是要使“緊耦合”變爲“鬆耦合”
使用場景
命令模式最常見的運用場景是:有時候需要向某些對象發送請求,但是並不知道請求的接受者是誰,也不知道被請求的操作是什麼。此時希望用一種鬆耦合的方式來設計程序,使得請求發送者和請求接受者能夠消除彼此之間的耦合關係
模式優點
- 降低對象之間的耦合度。
- 新的命令可以很容易地加入到系統中。
- 可以比較容易地設計一個組合命令。
- 調用同一方法實現不同的功能
舉個例子
現在的生活中,點外賣便利了我們的生活,訂餐的時候我們只需要再平臺上下單,可以不用知道是哪個究竟廚師的長相和聯繫方式,也不需要關係做菜的步驟和方法。這裏平臺的訂單就是把我們的請求都集中的command對象,訂單在平臺中通過程序被傳遞到商戶中,類似於我們到飯店吃飯,我們也無需知道廚師是誰,因爲有服務員把我們的點的單子記錄下來傳到廚師手中,這樣就解開了請求者和接收者之間的耦合關係
JavaScript中的命令模式
現在我們通過簡單js代碼的模擬下這個點單的程序:
<button id='addBtn'>添加</button>
<button id='delBtn'>刪除</button>
let Menu = {
add: function(dishName) {
console.log('添加' + dishName)
}
delete: function(dishName) {
console.log('刪除' + dishName)
}
}
let actionFun = function (btn, action) {
btn.onclick = action;
}
actionFun('addBtn', Menu.add)
actionFun('addBtn', Menu.del)
這樣用簡單的幾行代碼實現一個添加刪除的功能,現在我們繼續看下使用js模擬傳統面嚮對象語言的命令模式,看看有什麼不同
JavaScript實現傳統的命令模式
// 建命令
let Command = function (receiver) {
this.receiver = receiver
}
Command.prototype.execute = function () {
this.receiver.doCommand()
}
// 接收者 商家
let AddDish = function(dishName) {
AddDish.prototype.doCommand = function () {
console.log('添加' + dishName + '成功')
}
}
let DelDish = function(dishName) {
DelDish.prototype.doCommand = function () {
console.log('刪除' + dishName + '成功')
}
}
// 請求者 顧客
let Custormer = function(addDishCommand, delDishCommand) {
this.addDishCommand = addDishCommand;
this.delDishCommand = delDishCommand;
}
Custormer.prototype.addDish = function() {
this.addDishCommand.execute()
}
Custormer.prototype.delDish = function() {
this.delDishCommand.execute()
}
// 平臺 執行
let addDishCommand = new Command(new AddDish('番茄炒雞蛋'))
let delDishCommand = new Command(new DelDish('牛腩燉土豆'))
let custormer = new Custormer(addDishCommand, delDishCommand)
custormer.addDish();
custormer.delDish();
乍一看,這個過程好像沒什麼好處,似乎是給對象加了名爲execute的方法,並且command和接收者的存在複雜了我們前面的過程?傳統的命令模式將過程是的請求調用封裝在command的execute方法中,通過封裝方法調用,把運算塊包裝,command對象可以被隨意傳遞,因此在調用命令的時候,顧客(Client)不需要關心事情是如何進行的,這樣就達到了對請求者和接收者之間解耦的目的
小結
- 命令模式的本質是對命令的封裝,將發出的命令和執行命令的動作分隔開
- 對於命令模式而言,每個命令都是一次操作,請求者發起一個請求,需要執行一個操作,接收者收到命令時同樣要執行
- 命令模式允許請求發起者和請求接受者是黑盒模式,不必知道對方的接口是什麼,更不必關心其中的操作過程
- 命令模式使得請求本身成爲一個對象,這個對象和其他對象一樣可以被存儲和傳遞
- 命令模式引入了抽象命令接口,只有實現了抽象命令接口的具體命令才能與接受者相關聯
設計模式-百度百科[引用日期2019-06-16] ↩︎