代理模式 Proxy Pattern
介绍
- 使用者无权访问目标对象
- 中间加代理,通过代理做授权和控制
示例
类图:
classDiagram
Client --> ProxyImgProxyImg --> RealImg
class Client { + proxyImg: ProxyImg +main () void}
class ProxyImg { + realImg: RealImg +display() void}
class RealImg { + fileName: String +display() void -loadFromDisk() void}class RealImg { constructor(fileName) { this.fileName = fileName this.loadFromDisk() }
loadFromDisk() { console.log(`loading...${this.fileName}`) }
display() { console.log(`display...${this.fileName}`) }}
class ProxyImg { constructor(fileName) { this.realImg = new RealImg(fileName) }
display() { this.realImg.display() }}
const proxyImg = new ProxyImg('hello')proxyImg.display()应用场景
图片懒加载
const loadingImgUrl = 'xxx'const realImgUrl = 'xxx'
const myImage = (() => { const imgNode = document.createElement('img') document.append(imgNode) return { setSrc: (src) => { imgNode.src = src } }})()
const proxyImage = (() => { const img = new Image() img.onload = () => { myImage.setSrc(img.src) } return { setSrc: (src) => { myImage.setSrc(loadingImgUrl) img.src = src } }})()
proxyImage.setSrc(realImgUrl)网页事件代理
<div id="wrapper"> <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>const wrapper = document.getElementById('wrapper')// 监听所有 a 标签的点击事件wrapper.addEventListener('click', e => { const target = e.target if (target.nodeName === 'A') { console.log(target.innerHTML) }})jQuery $.proxy
$('#wrapper').click(function () { setTimeout($.proxy(function() { $(this).addClass('hello') }, this), 500)})ES6 Proxy
// 明星const star = { name: 'olu', age: 18, phone: 120110109,}
// 经纪人const agent = new Proxy(star, { get: function(target, key) { if (key === 'phone') { // 返回经纪人的手机号 return 12315 } if (key === 'price') { // 经纪人代替明星报价 return 521 } return target[key] }, set: function(target, key, val) { if (key === 'customPrice') { if (val < 520) { // 报价最低 520 throw new Error('olu 没有这么便宜!') } else { target[key] = val return true } } }})
console.log(agent.name) // 明星的console.log(agent.age) // 明星的console.log(agent.phone) // 经纪人的console.log(agent.price) // 经纪人提供agent.customPrice = 11 // error设计原则验证
- 代理类和目标类分离,隔离开目标类和使用者
- 符合开放封闭原则