前言
代理模式是指通过控制程序的读写,进而增强程序的功能
在生活中也可以找到许多代理模式的场景,比如租房,你并不会能直接去找房东租房,而是先会去找中介交涉需求,再由中介根据你的需求找到对应的房东签订合同,这里的中介就是房东的代理,中介帮房东的租房,而你也能租上房子。再比如海外商品代购,你必须通过代购员才能购买到海外商品,代购员就是海外商品的代理
现实生活中代理模式的使用场景数不胜数,代码中代理模式也是毫不逊色哦!!!
概念
为对象提供一种代理,以控制对这个对象的访问
在某些情况下,并不适合直接访问原对象,那就可以创建一个代理对象,让代理对象作为原对象和客户端沟通的桥梁
使用代理模式的目的是增强原对象,把原对象处理不了的场景交给代理对象处理,但是这样要注意增强功能!==新增功能,在JAVA语言中,原对象和代理对象要实现同一个接口,保证功能一致性,在JS中没有接口,需要开发者自觉遵守这个约定,也就是说原对象没有没有的功能,代理对象也不能有,代理对象功能应该和原对象的功能保持一致性,还有一点需要注意,如果原对象是函数,那么代理对象应该是函数,能够被客户端调用
这样做有3个好处
- 用户不需要关心对象是代理对象还是原对象,只需要关心是否得到想要的值
- 代理对象和原对象可以交换位置使用
- 去掉代理对象也不会影响源程序的正常运行
其实也很简单,就回到租房的例子,房东和中介的功能是一样的,只是中介的能力更强一点,但是就算没有中介,房东也可以租房
实例
代理模式的功能有很多,包含扩展、保护、缓存、惰性等功能,能力越大责任越大,代理模式也使用场景很多
扩展代理
例子:股票大涨,你不想自己洗脚,你就去找按摩小妹帮你洗脚
function runBathing() {
console.log("洗脚!!!");
}
// 按摩小妹
function girlBathing() {
console.log("办卡!!!");
runBathing()
}
girlBathing()
按摩小妹帮你洗脚,按摩小妹也就是你的洗脚代理,只是按摩小妹为了多赚点钱,会在推销办卡业务
保护代理
例子:某作者举行线下签售会,读者无法直接找作者签名,读者只有先和保镖对上口令,才可以找作者签名
let bodyguard = (function () {
let star = {
signName() {
console.log("签名成功~~~");
}
}
return {
signName(command) {
if (command == "天王盖地虎") {
star.signName()
} else {
console.log("假粉丝!!!");
}
}
}
})()
bodyguard.signName("天王盖地虎") // 签名成功~~~
bodyguard.signName("小鸡炖蘑菇") // 假粉丝!!!
保镖是作者的代理,保镖负责过滤假粉丝,保证了只有真粉丝才可以找作者签名
缓存代理
例子:程序中请求表格分页数据,为了防止用户频繁请求,需要缓存已经加载完成的页面数据
function createLoadDataProxy(getData) {
let cacheData = {}
return function (page) {
if (page in cacheData) {
console.log(`第${page}页数据走缓存`);
return cacheData[page]
}
return cacheData[page] = getData.call(this, page)
}
}
function loadTableData(page) {
let str = `加载第${page}页的数据`
console.log(str);
return str
}
let loadTableDataProxy = createLoadDataProxy(loadTableData)
loadTableDataProxy(1)
loadTableDataProxy(2)
loadTableDataProxy(1)
惰性代理
例子:学习委员帮老师收作业,等班上所以同学的作业都收完,再交给老师
interface Handle {
putAway(list: Array<any>): void
}
class Teacher implements Handle {
putAway(list): void {
console.log(`老师:作业收齐了,总共${list.length}份!!`);
}
}
class Learning implements Handle {
private teacher: Teacher = new Teacher()
private workList: Array<any> = []
putAway(list): void {
this.workList.push(...list)
console.log(`学习委员:作业收了${list.length}份!!`);
if (this.workList.length >= 3) {
this.teacher.putAway(this.workList)
}
}
}
let learning = new Learning()
learning.putAway([1, 2])
learning.putAway([3])
Vue数据驱动视图
在Vue2中,通过Object.defineProperty代理数据实现监听数据改变,在Vue3中采用Proxy,但是功能都是给原数据添加代理对象,修改代理对象不仅会改变原对象,还会修改页面内容,这已经是数据驱动视图的原理
let data = {
name: "李白"
}
let _data = {}
Object.defineProperty(_data, 'name', {
get() {
console.log('访问data.name属性触发')
// 收集使用了该属性的DOM元素
return data['name']
},
set(newValue) {
console.log('修改data.name属性触发')
// 更新收集的DOM元素内容
data['name'] = newValue
}
})
_data.name = "杜甫"
console.log(_data.name);
开启掘金成长之旅!这是我参与「掘金日新计划 · 2 月更文挑战」的第 26 天,点击查看活动详情