介绍
- 使用者无权访问目标对象
- 中间加代理,通过代理做授权和控制
示例
- 科学上网,访问 GitHub.com
- 明星经纪人
常见使用场景
- 网页事件代理
html
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Document</title>
</head>
<body>
<div id="div1">
<a href="#">a1</a>
<a href="#">a2</a>
<a href="#">a3</a>
<a href="#">a4</a>
<a href="#">a5</a>
<a href="#">a6</a>
</div>
<script src="https://cdn.bootcdn.net/ajax/libs/jquery/3.6.0/jquery.min.js"></script>
<script>
let div1 = document.getElementById('div1')
//监听a标签上的点击事件,不可能对a一个一个的去绑定
div1.addEventListener('click', function (e) {
let target = e.target
if (target.nodeName === 'A') {
console.log(target.innerHTML)
}
})
</script>
</body>
</html>
- jQuery的$.proxy
html
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Document</title>
</head>
<body>
<div id="div1">
<a href="#">a1</a>
<a href="#">a2</a>
<a href="#">a3</a>
<a href="#">a4</a>
<a href="#">a5</a>
<a href="#">a6</a>
</div>
<script src="https://cdn.bootcdn.net/ajax/libs/jquery/3.6.0/jquery.min.js"></script>
<script>
// $("#div1").click(function () {
// $(this).addClass("red");
// });
// $("#div1").click(function () {
// setTimeout(function () {
// // this 不符合期望
// $(this).addClass("red");
// }, 1000);
// });
// $("#div1").click(function () {
// var _this = this;
// setTimeout(function () {
// // _this 符合期望
// $(_this).addClass("red");
// }, 1000);
// });
// $("#div1").click(() => {
// setTimeout(() => {
// $(this).addClass("red");
// }, 1000);
// });
$('#div1').click(function () {
setTimeout(
$.proxy(function () {
$(this).addClass('red')
}, this),
1000
)
})
</script>
</body>
</html>
- es 6的proxy
javascript
//明星
let star = {
name: 'dd',
age: 25,
phone: '明星电话:189****05**',
}
//经纪人
let agent = new Proxy(star, {
//target是要代理的对象,key是要获取的属性值
get: function (target, key) {
if (key === 'phone') {
//返回经纪人的电话,不会把明星的电话直接给你
return '经纪人电话:189******3*'
}
if (key === 'price') {
//明星不报价,经纪人谈价格
return '12K'
}
return target[key]
},
set: function (target, key, value) {
if (key === 'customPrice') {
if (value < 100000) {
//最低10万
throw new Error('价格太低')
} else {
target[key] = value
return true
}
}
},
})
console.log(agent.name)
console.log(agent.phone)
console.log(agent.price)
agent.customPrice = 150000
console.log('agent.customPrice:' + agent.customPrice)
代理模式代码示例
javascript
class ReadImg {
constructor(fileName) {
this.fileName = fileName
this.loadFromDisk()
}
dispaly() {
console.log('display... ' + this.fileName)
}
loadFromDisk() {
console.log('loading... ' + this.fileName)
}
}
class ProxyImg {
constructor(fileName) {
this.realImg = new ReadImg(fileName)
}
dispaly() {
this.realImg.dispaly()
}
}
// test
let proxyImg = new ProxyImg('pic.png')
proxyImg.dispaly()
设计原理验证
- 代理类和目标类分离,隔离开目标类和使用者
- 符合开放封闭原则
区分
代理模式 VS 适配器模式
- 适配器模式:提供一个不同的接口(如不同版本的插头)
- 代理模式:提供一模一样的接口
代理模式 VS 装饰器模式
- 装饰器模式:扩展功能,原有功能不变且可直接使用
- 代理模式: 显示原有功能,但是经过限制或者阉割之后的