导言
单例模式、工厂模式(包括简单工厂、工厂方法和抽象工厂)、建造者模式和原型模式4种创建型模式在前面的篇幅都简单介绍了。今天我们继续来说说结构型设计模式中的代理模式。
代理模式其实在创建型模式的单例模式实例代码中稍微提到了:
let CreateDiv = function(html) {
this.html = html
this.init()
}
CreateDiv.prototype.init = function () {
let _div = document.createElement('div')
_div.innerHtml = this.html
document.body.appendChild(_div)
}
// 代理
let ProxySingletonCreateDiv = (function (html) {
let instance = null
return function (html) {
if (!instance) {
instance = new CreateDiv(html)
}
return instance
}
})()
const a = new ProxySingletonCreateDiv('a')
const b = new ProxySingletonCreateDiv('b')
console.log(a === b) // true
对实例是否存在的判断放在了另一个函数中,解耦了生成实例的构造方法。所以说,代理模式的主要功能是解耦原始类或方法或者说给原始类或方法添加附加功能,如控制访问权限等。
代理模式
在导言的代码实例中,代理模式所起的作用仅仅是用来判断了实例是否存在,你可能会说,这个直接放在创建实例的构造函数中不就行了,没有必要引入代理模式呀。你说的对,对于这种简单的例子不引入代理模式是完全可以的,只是判断实例是否存在是个最简单的情况,我们再来看个缓存计算的例子:
// 计算乘积
let mult = function () {
let a = 1
for (let i = 0; i < arguments.length; i++) {
a *= arguments[i]
}
return a
}
// 加入缓存代理
let proxyMult = (function () {
let cache = {}
return function () {
let args = Array.prototype.join.call(arguments, ',')
for (args in cache) {
return cache[args]
}
return cache[args] = mult.apply(this, arguments)
}
})()
proxyMult(1,2,3,4) // 24
proxyMult(1,2,3,4) // 24
mult函数仅专注于计算乘积的功能,对于来判断是否存在缓存的功能则放在代理的方法中来实现,符合单一职责原则,如果两个功能仍放在一个方法中,则代码耦合度会越来越高而难以维护。所以如果遇到更复杂的中间控制逻辑处理,可以拆分考虑引入代理模式。