命令模式

命令模式

定义

在软件系统中,“行为请求者”与“行为实现者”通常呈现一种“紧耦合”。但在某些场合,比如要对行为进行“记录、撤销/重做、事务”等处理,这种无法抵御变化的紧耦合是不合适的。在这种情况下,如何将“行为请求者”与“行为实现者”解耦?将一组行为抽象为对象,实现二者之间的松耦合。这就是命令模式(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] ↩︎

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