命令模式

命令模式

定義

在軟件系統中,“行爲請求者”與“行爲實現者”通常呈現一種“緊耦合”。但在某些場合,比如要對行爲進行“記錄、撤銷/重做、事務”等處理,這種無法抵禦變化的緊耦合是不合適的。在這種情況下,如何將“行爲請求者”與“行爲實現者”解耦?將一組行爲抽象爲對象,實現二者之間的鬆耦合。這就是命令模式(Command Pattern)。1

我們來看下命令模式的定義,明顯的關鍵詞我們都用黑體字標註出來了,行爲的請求者和執行者是關係對象,關鍵是要使“緊耦合”變爲“鬆耦合”

使用場景

命令模式最常見的運用場景是:有時候需要向某些對象發送請求,但是並不知道請求的接受者是誰,也不知道被請求的操作是什麼。此時希望用一種鬆耦合的方式來設計程序,使得請求發送者和請求接受者能夠消除彼此之間的耦合關係

模式優點

  1. 降低對象之間的耦合度。
  2. 新的命令可以很容易地加入到系統中。
  3. 可以比較容易地設計一個組合命令。
  4. 調用同一方法實現不同的功能

舉個例子

現在的生活中,點外賣便利了我們的生活,訂餐的時候我們只需要再平臺上下單,可以不用知道是哪個究竟廚師的長相和聯繫方式,也不需要關係做菜的步驟和方法。這裏平臺的訂單就是把我們的請求都集中的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)不需要關心事情是如何進行的,這樣就達到了對請求者和接收者之間解耦的目的

小結

  1. 命令模式的本質是對命令的封裝,將發出的命令和執行命令的動作分隔開
  2. 對於命令模式而言,每個命令都是一次操作,請求者發起一個請求,需要執行一個操作,接收者收到命令時同樣要執行
  3. 命令模式允許請求發起者和請求接受者是黑盒模式,不必知道對方的接口是什麼,更不必關心其中的操作過程
  4. 命令模式使得請求本身成爲一個對象,這個對象和其他對象一樣可以被存儲和傳遞
  5. 命令模式引入了抽象命令接口,只有實現了抽象命令接口的具體命令才能與接受者相關聯

  1. 設計模式-百度百科[引用日期2019-06-16] ↩︎

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章