代理模式是为一个对象提供一个代用品或占位符,以便控制对它的访问。
说人话就是:你想吃外卖变成,你委托骑手去店里拿外卖送到你手里。
代理模式的核心就是:丰富过程,结果不变。
以吃外卖的例子为例,我想吃外卖,这个事件的发起人是我,这个事件的结果是,吃外卖。
丰富一下这其中的过程:
我想吃外卖,我在APP上下单,骑手去店里拿外卖,骑手送外卖到我手里,我吃外卖。
再丰富一下过程:
我想吃外卖,我在APP上下单,骑手去店里拿外卖,店家说今天没进货,不开门营业,骑手到我家告诉我,食s啦馁!
把上述例字先写成代码,我们先来写核心部分,即,我吃外卖。
let I = {
getWaimai:function(name){
return store.cookingWaimai(name)
}
}
let store = {
cookingWaimai:function(name){
return cooking[name]()
}
}
let cooking = {
'花雕怪味鱼':function(){
//劈里啪啦一顿操作
return '花雕怪味鱼成品'
},
'无蛋黄':function(){
//劈里啪啦一顿操作
return '无蛋黄成品'
}
}
I.getWaimai('花雕怪味鱼') //花雕怪味鱼成品
在上述代码中,有两个主题对象,一个是我,另一个是商家,我可以直接把get外卖的请求发给store,可以理解为我去店里,然后点了一份外卖,商家直接就把外卖端上来给我了。
在我和商家之间,现在加个骑手,代码是怎么样的呢?
let I = {
getWaimai:function(name){
return qishou.cookingWaimai(name)
}
}
let qishou = {
cookingWaimai:function(name){
// 先去店里拿外卖
// 此处省略一万行代码
// 再送到顾客手里
return store.cookingWaimai(name)
}
}
let store = {
cookingWaimai:function(name){
return cooking[name]()
}
}
let cooking = {
'花雕怪味鱼':function(){
//劈里啪啦一顿操作
return '花雕怪味鱼成品'
},
'无蛋黄':function(){
//劈里啪啦一顿操作
return '无蛋黄成品'
}
}
I.getWaimai('花雕怪味鱼') //花雕怪味鱼成品
这里我委托外卖员拿到了store.cookingWaimai()的结果,中间省去了骑手如何拿外卖以及如何送外卖的过程。这样写有什么好处呢?
1.我可以委托任何人来帮我拿外卖,今天是饿了吗骑手,明天就是美团骑手了,我只需要在getWaimai函数里改一个小细节就能实现,甚至我可以直接去店里吃。
2.骑手作为委托人可以在我不需要亲自去店里的情况下传达一些店里的信息给我,比如今天双休日,骑手就可以直接告诉我商家双休日不营业,从而过滤掉我的吃外卖请求。
事实上代理模式最大的好处就是,你可以随时修改某一段业务逻辑并保证结果是正确的。我们来看一段常见的代码。
function init(){
// 调用一大堆接口...
// 整合业务逻辑...
// 渲染页面...
}
function change(){
// 修改了页面里某个东西
init()
}
事实上你init函数里99%的接口调用和业务逻辑处理都是重复的,你只是改了某一个数值并想更新跟这个数值有关的一些页面信息,这时候你就可以用代理模式来控制init函数里哪些接口是需要更新的,哪些业务代码是需要执行的。如下所示
// 用锁的概念来判断哪些业务代码需要执行
function init(lock1,lock2,lock3)
// 调用一大堆接口...
// 整合业务逻辑...
// 渲染页面...
}
function change(){
// 修改了页面里某个东西
daili()
}
function daili(){
// 写一大堆条件判断
init(lock1,lock2,lock3)
}
改写后的代码,如果某天哪些锁失效了(或者帮你维护代码的人看不懂你写的代码),你只需要把锁直接写死(true or false)即可。甚至你可以直接在change函数里面调用init(true,true,true)来保证正确的结果。