JavaScript设计模式之代理模式

发布于 / 学习

介绍

  • 使用者无权直接访问目标对象
  • 中间使用代理,通过代理的方式做授权和控制

实例

  • 科学上网
  • 明星经纪人

UML

image

代码演示

        class RealImg{
        constructor(fileName){
            this.fileName = fileName;
            this.loadFromDisk()
        }

        display(){
            console.log('display.....'+ this.fileName)
        }

        loadFromDisk(){
            console.log('from disk.....'+ this.fileName)
        }

    }

    class ProxyImg{
        constructor(fileName){
            this.realImg = new RealImg(fileName);
        }
        display(){
            this.realImg.display()
        }
    }

    //测试
    let proxyImg = new ProxyImg('1.png')
    proxyImg.display()

场景

  • 网页事件代理
  • Es6 Proxy
  • jQ $.proxy

网页事件代理

    <div id="div1">
        <a href="#">a1</a>
        <a href="#">a2</a>
        <a href="#">a3</a>
        <a href="#">a4</a>
        <a href="#">a5</a>
    </div>
     var div1 = document.getElementById('div1');
    div1.addEventListener('click',function (e) {
        var target = e.target
        if(target.nodeName ==='A'){
            alert(target.innerHTML)
        }
    })

jQ $.proxy

    <div id="div1">
        <a href="#">a1</a>
        <a href="#">a2</a>
        <a href="#">a3</a>
        <a href="#">a4</a>
        <a href="#">a5</a>
    </div>
     $('#div1').click(function () {
       var _this = this
       setTimeout(function () {
           //直接$(this) 的话当前this 不是 $('#div1')
           $(_this).addClass('red')
       },1000)
   })

    //使用代理
   $('#div1').click(function () {
       setTimeout($.proxy(function () {
           //直接$(this) 的话当前this 不是 $('#div1')
           $(this).addClass('red')
       },this),1000);
   })

ES6 Proxy

     //定义一个real 对象
    let star = {
        name:'w候人兮猗',
        age:22,
        phone:'15955041111'
    }
    //定义一个代理
    let agent = new Proxy(star,{
        get:function (target,key) {
            if(key === 'phone'){
                //返回代理的电话
                return '1123123'
            }
            if(key === 'price'){
                //原对象不做这件事 返会的是代理的
                return '120000'
            }
            return target[key]
        },
        set:function (target, key, value) {
            if(key === 'customPrice'){
                if(value < 10000){
                    alert('价格太低')
                }else{
                    target[key] = value
                    return true
                }
            }
        }
    })

    // 测试
    console.log(agent.name)
    console.log(agent.age)
    console.log(agent.phone)
    console.log(agent.price)

    agent.customPrice = 15000000;
    console.log(agent.customPrice)

比较

  • 代理模式 – 适配器模式
  1. 适配器模式:提供一个不同的接口
  2. 代理模式:提供一个一模一样的接口代理上去
  • 代理模式 – 装饰器模式
  1. 装饰器模式:拓展功能,之前的功能不变
  2. 代理模式:显示原有功能,但是进过限制和阉割

代码:

https://github.com/ahwgs/design-pattern-learning/tree/master/7.JavaScript%E8%AE%BE%E8%AE%A1%E6%A8%A1%E5%BC%8F%E4%B9%8B%E4%BB%A3%E7%90%86%E6%A8%A1%E5%BC%8F

本文采用 CC BY-NC-SA 3.0 Unported 协议进行许可
本文链接: https://www.ahwgs.cn/javascriptshejimoshizhidailimoshi.html