Skip to main content

代理模式

代理模式:使用者无权访问目标对象,中间加代理,通过代理做授权和控制。

明星经纪人:比如有个演出,要请明星,要先联系经纪人。 或者理解为:为一个对象提供一个代用品或者占位符,以便控制对它的访问。例如图片懒加载、中介等。

示例 1

/**
* pre:代理模式
* 小明追求A,B是A的好朋友,小明比不知道A什么时候心情好,不好意思直接将花交给A,
* 于是小明将花交给B,再由B交给A.
*/

// 花的类
class Flower{
constructor(name){
this.name = name
}
}

// 小明拥有sendFlower的方法
let Xiaoming = {
sendFlower(target){
var flower = new Flower('玫瑰花')
target.receive(flower)
}
}

// B对象中拥有接受花的方法,同时接收到花之后,监听A的心情,并且传入A心情好的时候函数
let B = {
receive(flower){
this.flower = flower
A.listenMood(()=>{
A.receive(this.flower)
})
}
}

// A接收到花之后输出花的名字
let A = {
// 收到花
receive(flower){
console.log(`A收到了${flower.name}`)
}
// 条件:1s后心情好
listenMood(func){
setTimeout(func,1000)
}
}
Xiaoming.sendFlower(B)

示例 2

ES6 Proxy

其实在 ES6 中,已经有了 Proxy,这个内置的函数。我们来用一个例子来演示一下他的用法。这是一个明星代理的问题。

let star={
name : "张XX",
age:25,
phone : "1300001111"
}
// 代理
let agent = new Proxy(star,
{
get:function(target,key){
if(key === "phone"){
return "18839552597"
}else if(key === "name"){
return "张XX"
}else if(key === "price"){
return "12W"
}else if(key === "customPrice"){
return target.customPrice
}
},
set:function(target,key,value){
if(key === "customPrice"){
if(value < "10"){
console.log("太低了!!!")
return false
}else{
target[key] = value
return true
}
}
}
}
)

console.log(agent.name)
console.log(agent.price)
console.log(agent.phone)
console.log(agent.age)
agent.customPrice = "12"
console.log(agent)
console.log(agent.customPrice)

示例 3

虚拟代理用于图片的预加载:图片很大,页面加载时会空白,体验不好,所以我们需要个占位符,来短暂替代这个图片,等图片加载好了放上去。

let myImage = (function(){
let img = new Image
document.body.appendChild(img)
return {
setSrc:(src)=>{
img.src = src
}
}
})()

// 图片代理
let imgProxy =(function(){
let imgProxy = new Image
// 这个地方我使用了setTimeout来增强演示效果,否则本地加载太快,根本看不到。
imgProxy.onload=function(){
setTimeout(()=>{
myImage.setSrc(this.src)
},2000)
}

return (src)=>{
myImage.setSrc("../../img/bgimg.jpeg")
// 使用占位图
imgProxy.src=src
}
})()

imgProxy("../../img/background-cover.jpg")

设计原则验证

代理类和目标类分离,隔离开目标类和使用者 符合开放封闭原则