设计模式(五)-代理模式

代理模式

为其他对象提供一种代理以控制对这个对象的访问.在某些情况下,一个对象不适合或者不能直接引用另一个对象,而代理对象可以在客户端和目标对象之间起到中介的作用.

  • 图例


    image.png
  • 代码实现
class Google{
    get(url){
        return `google:${url}`
    }
}
class Proxy{
    constructor(){
       this.google=new Google()
    }
    get(url){
        return this.google.get(url)
    }
}

let proxy=new Proxy();
let result=proxy.get('http://www.google.com');
console.log(result) //google:http://www.google.com
  • 缓存代理
//计算阶乘 普通方式
function mult(n){
    if(n<=1){
        return 1
    }else{
        return n*mult(n-1)
    }
}

let result=mult(5); //120
console.log(result)

//缓存代理
let result=(function(){
    return function(n){
        let cache={}
        function mult(n){
            if(cache[n]!==undefined){
                return cache[n];
            } 
            let result
            if(n<=1){
               result=1
            }else{
               result= n*mult(n-1)
            }
            cache[n]=result;
            console.log(cache) //{ '1': 1, '2': 2, '3': 6, '4': 24, '5': 120 }
            return result
        }
        return  mult(n)
    }
})()

console.log(result(5))
  • 虚拟缓存
let myImage=(function(){
    let img=document.createElement('img');
    document.body.appendChild(img);
    return {
        setSrc:function(src){
            img.src=src
        }
    }
})()

let proxyImage=(function(){
    let image=new Image;
    image.onload=function(){
        myImage.setSrc(this.src)
    }
    return {
        setSrc:function(src){
            myImage.setSrc('loading.gif')
            //赋值整上
            image.src=src
        }
    }
})()

proxyImage.setSrc( '1.jpg' );
  • es6 Proxy(代理)
// 不能直接修改children 通过mither代理 间接修改children
let children={age:18,name:'wx'};
let mither=new Proxy(children,{
    get(target,key){
        if(key=='age'){
            return target[key]+2
        }else{
            return target[key]
        }
    },
    set(target,key,value){
       return target[key]=value
    }
})
console.log(mither.age)  //20
mither.height=123
console.log(children) // { age: 18, name: 'wx', height: 123 }
  • 应用场景

1.事件委托

  <ul id="ulList">
        <li>1</li>
        <li>2</li>
        <li>3</li>
    </ul>
   <script>
          let ulList=document.querySelector("#ulList");
          ulList.addEventListener('click',function(event){
              alert(event.target.innerHTML)
          })
   </script>

2.jquery.proxy

 $('#ulList').click(function(){
      $(this).addClass('red')
 })

// this指向改变 
$('#ulList').click(function() {
   setTimeout(function() {
      // Problem! In this function "this" is not our element!
      $(this).addClass('red')
    }, 1000);
 })

//$.proxy
$('#ulList').click(function() {
     setTimeout($.proxy(function() {
         $(this).addClass('red')
     },this), 1000);
})

$.proxy的实现

window.$.proxy=function(fn,arg){
     fn.call(arg,arguments)
}
$('#ulList').click(function() {
     setTimeout($.proxy(function() {
           $(this).addClass('red')
     },this), 1000);
})

3.防抖

function debounce(fn,wait){
    let timeout=null;
    if(timeout!==null) clearTimeout(timeout)
    timeout=setTimeout(() => {
        fn.apply(this,arguments);
        timeout=null
    }, wait);
}

function handle() {
    console.log(new Date());
}
window.addEventListener('scroll',debounce(handle,1000))
代理模式 区别
代理模式vs适配器模式 适配器模式可以提供不同的接口,代理模式必须提供一摸一样的接口
代理模式vs装饰器模式 装饰器模式原来的功能不变可以继续使用,代理模式改变原有的功能
优点
1.职责清晰:真实的角色就是实现实际的[业务逻辑],不用关心其他非本职责的事务,通过后期的代理完成一件完成事务,附带的结果就是编程简洁清晰。
2.代理对象可以在客户端和目标对象之间起到中介作用,这样起到了中介保护目标对象的作用
3.高扩展性
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容