代理模式代理模式(ProxyPattern),也称为委托模式,为目标对象创建一个代理对象,控制对目标对象的访问,也可以是理解为外部暴露接口不是原始对象。通俗地说,生活中也有比较常见的代理模式:中介、代销、经纪人等等。这种模式的意义在于,当来访者和受访者不方便直接访问/联系时,提供一个替代者来处理交易过程。实际访问是替代。替代者对事务做了一些处理/过滤后,再传递给本体对象,减轻本体对象的负担。通用代理模式保护代理虚拟代理缓存代理。..实现保护代理:/***保护代理的简单实现*客户端向服务器发送请求*代理转发请求到服务器*服务器处理请求*///改进前constRequest=function(){};constclient={requestTo:(server)=>{constreq=newRequest();服务器.receiveRequest(req);},};constserver={handleRequest:(request)=>{console.log('receiverequest:',request);},};constproxy={receiveRequest:(request)=>{console.log('proxyrequest:',request);服务器.handleRequest(请求);},};client.requestTo(代理);//改进的constproxy={receiveRequest:(request)=>{//验证身份constpass=validatePassport(request);if(pass){//服务器就绪后监听代理请求server.listenReady((){console.log('proxyrequest:',request);server.handleRequest(request);});}},};Virtualproxy:虚拟代理就是延迟一些昂贵的对象或方法,直到真正需要它们时才创建和执行//图片延迟加载constimg=(()=>{constimgNode=document.createElement('img');我是gNode.style.width='200px'document.body.appendChild(imgNode);返回{setSrc:(src)=>{imgNode.src=src;},setLoading:()=>{imgNode.src='./img/loading.gif'}};})();constproxyImg=((source)=>{//头像图片对象consttempImg=newImage();//监听资源加载完成,将资源替换为实体图片对象tempImg.onload=function(){source.setSrc(this.src);};return{//代理开始设置实体对象为加载状态,使用别名对象开始加载图片资源setSrc:(src)=>{source.setLoading()tempImg.src=src;}}})(img);proxyImg.setSrc('https://static-prod.retech.us/onder-cender/DoorDash.svg')//----------------------------------------------------------//合并http请求//上传请求letupload=function(ids){$.ajax({data:{id:ids}})}//代理合并请求letproxy=(function(){letcache=[],timer=null;returnfunction(id){cache[cache.length]=id;如果(定时器)返回假;timer=setTimeout(function(){upload(cache.join(','));clearTimeout(timer);timer=null;cache=[];},2000);}})();//绑定点击事件letcheckbox=document.getElementsByTagName("input");for(vari=0,c;c=checkbox[i++];){c.onclick=function(){if(this.checked===true){proxy(this.id);}}}}缓存代理:缓存代理可以提供临时存储作为一些昂贵计算的结果。在接下来的操作中,如果传入的参数和之前一样,那么就可以直接返回之前存储的操作结果/***对于一些比较消耗性能的操作*,可以缓存结果*获取结果的时候,他们都是先从缓存中取出,缓存中没有进一步计算*/letfibonacci=function(n){if(n===1||n===0)returnn;返回斐波那契(n-1)+斐波那契(n-2);}//缓存代理letproxy=(function(fn){letcache={};returnfunction(){letargs=Array.prototype.join.call(arguments,',');if(argsincache){returncache[args];}returncache[args]=fn.apply(this,arguments);}})(斐波那契);proxy(3)实战Vue中的代理模式://将数据、方法、计算属性等代理到组件实例letvm=newVue({data:{msg:'hello',vue:'vue'},computed:{helloVue(){returnthis.msg+''+this.vue}},mounted(){console.log(this.helloVue)}})源代码分析:导出函数代理(target:Object,sourceKey:string,key:string){sharedPropertyDefinition.get=functionproxyGetter(){returnthis[sourceKey][key]}sharedPropertyDefinition.set=functionproxySetter(val){this[sourceKey][key]=val}Object.defineProperty(target,key,sharedPropertyDefinition)}exportfunctioninitState(vm:Component){vm._watchers=[]constopts=vm.$optionsif(opts.props)initProps(vm,opts.props)if(opts.methods)initMethods(vm,opts.methods)if(opts.data){initData(vm)}else{observe(vm._data={},true/*asRootData*/)}if(opts.computed)initComputed(vm,opts.computed)if(opts.watch&&opts.watch!==nativeWatch){initWatch(vm,opts.watch)}}functioninitData(vm:Component){letdata=vm.$options.data//初始化_data,component中的data是一个函数,调用函数返回结果//否则直接返回数据data=vm._data=typeofdata==='函数'?getData(数据,虚拟机):数据||{}if(!isPlainObject(data)){data={}process.env.NODE_ENV!=='production'&&warn('datafunctionsshouldreturnanobject:\n'+'https://img.ydisp.cn/news/20221130/dlgyufwtyqy.htmlvm)}//在实例上代理数据//获取数据中的所有属性constkeys=Object.keys(data)//获取道具/方法constprops=vm.$options.propsconstmethods=vm.$options.methodsleti=keys.length//判断data上的成员是否与props/methods同名while(i--){constkey=keys[i]if(process.env.NODE_ENV!=='production'){if(methods&&hasOwn(methods,key)){warn(`Method"${key}"已经被定义为数据属性。`,vm)}}if(props&&hasOwn(props,key)){process.env.NODE_ENV!=='production'&&warn(`数据属性“${key}”已声明为道具。`+`改用道具默认值。`,vm)}elseif(!isReserved(key)){proxy(vm,`_data`,key)}}//观察数据//响应式处理observe(data,true/*asRootData*/)}总结在面向对象编程中,合理使用代理模式可以很好它完美体现了以下两个设计原则:单一职责原则:面向对象设计鼓励将不同的职责分配给细粒度的对象。Proxy在不影响原对象的情况下,在原对象的基础上衍生出功能,符合松耦合。高内聚设计理念Open-Closed原则:代码可以随时从程序中移除,而无需修改代码的其他部分。在实际场景中,随着版本的迭代,不再需要代理的原因可能有很多。然后你可以很容易地用原始对象替换代理对象。代理模式Proxy的作用主要体现在三个方面:拦截和监控外部对对象的访问,降低对象的复杂度,复杂操作前的验证操作。管理所需的资源
