《javascript设计模式与开发实践》读书笔记(8)
本次笔记记录本周学习的中介者模式和装饰者模式。
中介者模式
中介者模式就是通过一个中介者对象来解除各对象之间的紧耦合关系。如果各对象之间耦合紧密,那么当一个对象需要改变的时候,往往需要相应改变与之相关联的其它对象,如果使用中介者模式,那么你只需要更改定义了各对象之间关联关系的中介者对象即可。
中介者模式本身比较容易理解,书中也主要通过两个例子来让读者加深对中介者模式的理解。这里借用书中例子来进行对中介者模式的实践。中介者模式的例子
考虑这样一个需求,一个手机商品的购买页,买家需要选择手机颜色、内存等,根据买家所选的参数,展示手机库存量。我们在这个例子中引入中介者模式,当颜色、内存等变化的时候,通知中介者哪些参数变化,剩余的事情全部交予中介者完成。如果以后需要加入其它参数,原有的颜色、内存等对象不需要做过多的修改。
var goods = { //商品库存数据
'red|32G': 3,
'red|16G': 10,
'blue|32G': 0,
'blue|16G': 7
}
var mediator = (function(){
var colorSelect = document.getElementById('colorSelect')
var memorySelect = document.getElementById('memorySelect')
var numberInput = document.getElementById('numberInput')
var colorInfo = document.getElementById('colorInfo')
var memoryInfo = document.getElementById('memoryInfo')
var numberInfo = document.getElementById('numberInfo')
var nextBtn = document.getElementById('nextBtn')
return {
changed: function(obj){
var color = colorSelect.value,
memory = memorySelect.value,
number = numberInpur.value,
stock = goods[color + '|' + memory]
if(obj === colorSelect){
colorInfo.innerHTML = color
}else if(obj === memorySelect){
memoryInfo.innerHTML = memory
}else if(obj === numberInput){
numberInput.innerHTML = number
}
if(!color){
nextBtn.disabled = true
nextBtn.innerHTML = '请选择手机颜色'
return
}
if(!memory){
nextBtn.disabled = true
nextBtn.innerHTML = '请选择内存大小'
return
}
if(Number.isInteger(number - 0) && number > 0){
nextBtn.disabled = true
nextBtn.innerHTML = '请输入正确的购买数量'
return
}
nextBtn.disabled = false
nextBtn.innerHTML = '放入购物车'
}
}
})()
colorSelect.onchange = function(){
mediator.changed(this)
}
memorySelect.onchange = function(){
mediator.changed(this)
}
numberInput.onchange = function(){
mediator.changed(this)
}
引入中介者对象,可以想像,如果以后增加其它参数,我们也只需改动mediator对象即可,不要动其它位置代码。
总结
中介者模式就是通过引入一个中介者对象,把各对象之间的耦合关系定义在此中介者对象中,从而降低各对象的耦合,便于维护。
装饰者模式
定义:
给对象动态地增加指责的模式称为装饰者模式。装饰者模式能够在不改变自身的基础上,在程序运行期间给对象动态地添加指责。装饰函数
在js中可以很方便地给某个对象扩展属性和方法,但却很难在不改动某个函数源代码的情况下,给该函数添加一些额外的功能。在代码运行期间,我们很难切入某个函数的执行环境。如下例子:
var a = function(){
alert(1)
}
var _a = a
a = function(){
_a()
alert(2)
}
a()
通常我们通过保存原引用的方式就可以改写某个函数,但是通常这样通常会改变原函数的this指向,我们需要借助apply来指向正确的this,但这样很不方便,下面介绍AOP,来解决此问题。
用AOP装饰函数
我们在Function.prototype上增加before和after方法:
Function.prototype.before = function(beforeFn){
var _self = this
return function(){
beforeFn.apply(this, arguments)
return __self.apply(this, arguments)
}
}
Function.prototype.after = function(afterFn){
var _self = this
return function(){
var ret = _self.apply(this, arguments)
afterFn.apply(this, arguments)
return ret
}
}
有了before和after函数,我们就可以很方便的改写原函数。
var a = function(){
alert(1)
}
a = a.after(function(){
alert(2)
}).after(function(){
alert(3)
})
a()
总结
装饰者模式和***模式最重要的区别在于它们的意图和设计目的。***模式的目的是,当直接访问本体不方便或者不符合需要时,为这个本体提供一个替代者。装饰者模式的作用就是对象动态加入行为。AOP装饰函数让代码看起来更简洁和便于理解,但本身函数的编写用到一些技巧还需要练习理解。
#笔记##读书笔记##设计#