# 代理模式
# 介绍
- 使用者无权访问目标对象
- 中间加代理,通过代理做授权和控制
# 示例
- 科学上网,访问 github.com
- 明星经纪人
# UML 类图
# 代码演示
class ReadImg {
constructor(fileName) {
this.fileName = fileName
this.loadFromDisk() // 初始化从硬盘中加载, 模拟
}
display() {
console.log('display...' + this.fileName)
}
loadFromDisk() {
console.log('loading...' + this.fileName)
}
}
class ProxyImg {
constructor(fileName) {
this.realImg = new ReadImg(fileName)
}
display() {
this.realImg.display()
}
}
// test
let proxyImg = new ProxyImg('1.png')
proxyImg.display()
# 场景
# 网页事件代理
let div1 = document.getElementById('div1')
// 不可能每个a标签加一个点击事件,通过给父级添加一个代理实现
div1.addEventListener('click', function (e) {
let target = e.target
// 判断如果点击的是a标签
if (target.nodeName === 'A') {
console.log(target.innerHTML)
}
})
# jQUery $.proxy
$('#div1').click(function () {
const _this = this
setTimeout(function () {
// console.log(this)// windows
// $(this).css('background-color', 'yellow')
$(_this).css('background-color', 'yellow')
}, 1000);
})
// 或者使用$.proxy
$('#div1').click(function () {
setTimeout($.proxy(function () {
$(this).css('background-color', 'yellow')
}, this), 1000);
})
# ES6 Proxy
// 明星
let star = {
name: 'jiegiser',
age: 18,
phone: '88888888888'
}
// 经纪人
let agent = new Proxy(star, {
get: function(target, key) {
if(key === 'phone') {
// 返回经纪人自己的电话
return 33333333333
}
if(key === 'price') {
// 明星不报价,经纪人报价
return 120000
}
return target[key]
},
set: function(target, key, val) {
if(key === 'customPrice') {
if(val < 100000) {
// 最低10w
throw new Error('价格太低')
} else {
target[key] = val
return true
}
}
}
})
// test
console.log(agent.name)
console.log(agent.age)
console.log(agent.phone)
console.log(agent.price)
agent.customPrice = 150000
console.log(agent.customPrice)
# 设计原则
- 代理类和目标类分离,隔离开目标类和使用者
- 符合开放封闭原则
阅读量: