【第六章】代理模式

定义: 为一个对象提供一个代用品或占位符,以控制对它的访问
关键:当客户不方便直接访问一个对象或者不满足需求的时候,提供一个替身对象来控制对这个对象的访问,客户实际上访问的是替身对象。替身对象对请求作出一些处理之后,再把请求转交给本体对象

不使用代理模式: 客户 ——> 本体
使用代理模式: 客户 ——> 代理 ——> 本体

一个解释代理模式的例子

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
/*
M 直接送花给 A
*/
var Flower = function(){}
var M = {
sendFlower: function(target){
var flower = new Flower()
target.receiveFlower(flower)
}
}
var A = {
receiveFlower: function(flower){
console.log('收到花'+flower)
}
}
M.sendFlower(A)

/*
M 通过 B 送花给 A
*/
var Flower = function(){}
var M = {
sendFlower: function(target){
var flower = new Flower()
target.receiveFlower(flower)
}
}
var B = {
receiveFlower: function(flower){
A.receiveFlower(flower)
}
}
var A = {
receiveFlower: function(flower){
console.log('收到花'+flower)
}
}
M.sendFlower(B)

/*
现在我们改变故事的背景设定,假设当 A 在心情好的时候收到花,小明表白成功的几率有60%,而当 A 在心情差的时候收到花,小明表白的成功率无限趋近于 0。
小明跟 A 刚刚认识两天,还无法辨别 A 什么时候心情好。如果不合时宜地把花送给 A,花被直接扔掉的可能性很大
但是 A 的朋友 B 却很了解 A,所以小明只管把花交给 B,B 会监听 A 的心情变化,然后选择 A 心情好的时候把花转交给 A,
*/
var Flower = function () {}
var M = {
sendFlower: function (target) {
var flower = new Flower()
target.receiveFlower(flower)
}
}
var B = {
receiveFlower: function (flow) {
A.hasGoodMood(function(){
A.receiveFlower(flow)
})

}
}
var A = {
receiveFlower: function (flow) {
console.log('get flower' + flow)
},
hasGoodMood: function(fn){
setTimeout(() => {
fn()
}, 1000);
}
}

M.sendFlower(B)

保护代理和虚拟代理

代理B可以帮助A过滤掉一些请求的叫做保护代理 (通过B来控制对A的访问)
代理 B 会选择在 A 心情好时再执行 new Flower叫作虚拟代理。 (虚拟代理把一些开销很大的对象,延迟到真正需要它的时候才去创建)

1
2
3
4
5
6
7
8
9
var B = {
receiveFlower: function(flower){
A.listenGoodMood(function(){ //监听A的好心情
var flower = new Flower() //延迟创建flower对象
A.receiveFlower(flower)
})
}
}

虚拟代理实现图片预加载

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25

var oImg = (function(){
var imgNode = document.createElement('img')
document.body.appendChild(imgNode)
return {
setSrc : function(src){
imgNode.src = src
}
}
})()

//代理对象
var proxyImage = (function(){
var img = new Image() //获取的img对象
img.onload = function(){
oImg.setSrc(this.src) //img.src
}
return {
setSrc: function(src){
oImg.setSrc('./loading.gif')
img.src = src
}
}
})()
proxyImage.setSrc('http://....jpg')

代理的意义

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
//不使用代理的方式
var oImg = (function(){
var imgNode = document.createElement('img')
document.body.appendChild(imgNode)
var img = new Image
img.onload = function(){
imgNode.src = img.src
}
return {
setSrc : function(src){
imgNode.src = './timg.jpg'
img.src = src
}
}
})()
oImg.setSrc('https://ss3.bdstatic.com/70cFv8Sh_Q1YnxGkpoWK1HF6hhy/it/u=629448732,2965351611&fm=15&gp=0.jpg')

单一职责原则:为了减少代码的耦合性,方便维护和修改

代理和本体接口的一致性

调用时的代理接口和本地接口名称一致 也通过直接返回函数

优点:

  1. 用户可以放心地请求代理,他只关心是否能得到想要的结构
  2. 在任何使用本体的地方都可以替换成使用代理
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    var myImage = (function(){
    var imgNode = document.createElement('img')
    document.appendChild(imgNode)
    return function(src){
    imgNode.src = src
    }
    })()

    var proxyImage = (function(){
    var img = new Image
    img.onload = function(){
    myImage( this.src )
    }
    return function(src){
    myImage('./timg.jpg')
    img.src = src
    }
    })()
    proxyImage('https://ss3.bdstatic.com/70cFv8Sh_Q1YnxGkpoWK1HF6hhy/it/u=629448732,2965351611&fm=15&gp=0.jpg')

扫一扫,分享到微信

微信分享二维码
  • Copyrights © 2019-2023 John Doe
  • Visitors: | Views:

请我喝杯咖啡吧~

支付宝
微信