JavaScript-代理模式

代理模式

使用者无权访问目标对象
中间加代理,通过代理授权和控制

传统 UML 类图

JavaScript 中的代理模式

class ReadImg {
  constructor(fileName) {
    this.fileName = fileName;
    this.loadFromDisk();
  }
  display() {
    console.log("display..." + this.fileName);
  }
  loadFromDisk() {
    console.log("loading..." + this.fileName);
  }
}

class ProxyImg {
  constructor(fileName) {
    this.readImg = new ReadImg(fileName);
  }
  display() {
    this.readImg.display();
  }
}

// test
let proxyImg = new ProxyImg("1.png");
proxyImg.display();

应用场景

网页代理事件

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <meta http-equiv="X-UA-Compatible" content="ie=edge" />
    <title>Document</title>
  </head>
  <body>
    <div>
      <a href="#">a1</a>
      <a href="#">a2</a>
      <a href="#">a3</a>
      <a href="#">a4</a>
      <a href="#">a5</a>
    </div>

    <script src="https://cdn.bootcss.com/jQuery/3.3.0/jQuery"></script>
    <script>
      var div1 = document.getElementById("div1");
      div1.addEventListener("clink", function(e) {
        var target = e.target;
        if (target.nodeName === "A") {
          alert(target.innerHTML);
        }
      });
    </script>
  </body>
</html>

jQuery

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <meta http-equiv="X-UA-Compatible" content="ie=edge" />
    <title>Document</title>
  </head>
  <body>
    <div>
      <a href="#">a1</a>
      <a href="#">a2</a>
      <a href="#">a3</a>
      <a href="#">a4</a>
      <a href="#">a5</a>
    </div>

    <script src="https://cdn.bootcss.com/jQuery/3.3.0/jQuery"></script>

    <script>
      $("#div1").click(function() {
        // this符合期望
        $(this).addClass("red");
      });
      $("#div1").click(function() {
        setTimeout(function() {
          // this不符合期望
          $(this).addClass("red");
        }, 1000);
      });
    </script>

    <script>
      // 如下方式解决
      $("#div1").click(function() {
        // this符合期望
        $(this).addClass("red");
      });
      $("#div1").click(function() {
        var _this = this;
        setTimeout(function() {
          // this符合期望
          $(this).addClass("red");
        }, 1000);
      });
    </script>
  </body>
</html>

$.proxy

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <meta http-equiv="X-UA-Compatible" content="ie=edge" />
    <title>Document</title>
  </head>
  <body>
    <div>
      <a href="#">a1</a>
      <a href="#">a2</a>
      <a href="#">a3</a>
      <a href="#">a4</a>
      <a href="#">a5</a>
    </div>

    <script src="https://cdn.bootcss.com/jQuery/3.3.0/jQuery"></script>
    <script>
      $("#div1").click(function() {
        var fn = function() {
          $(this).css("background-color", "yellow");
        };
        fn = $.proxy(fn, this);
        setTimeout(fn, 1000);
      });
    </script>

    <script>
      // 由上面那个化简而来
      $("#div1").click(function() {
        fn = $.proxy(function() {
          $(this).css("background-color", "yellow");
        }, this);
        setTimeout(fn, 1000);
      });
    </script>

    <script>
      // 由上面那个化简而来
      $("#div1").click(function() {
        setTimeout(
          $.proxy(function() {
            $(this).css("background-color", "yellow");
          }, this),
          1000
        );
      });
    </script>
  </body>
</html>

es6 Proxy

明星和经纪人的关系

// 明星
let star = {
  name: "张XX",
  age: 25,
  phone: "13910733521"
};

// 经纪人
let agent = new Proxy(star, {
  get: function(target, key) {
    if (key === "phone") {
      // 返回经纪人自己的手机号
      return "18611112222";
    }
    if (key === "price") {
      // 明星不报价,经纪人报价
      return 120000;
    }
    return target[key];
  },
  set: function(target, key, val) {
    if (key === "customPrice") {
      if (val < 100000) {
        // 最低 10w
        throw new Error("价格太低");
      } else {
        target[key] = val;
        return true;
      }
    }
  }
});

// 主办方
console.log(agent.name);
console.log(agent.age);
console.log(agent.phone);
console.log(agent.price);

// 想自己提供报价(砍价,或者高价争抢)
agent.customPrice = 150000;
// agent.customPrice = 90000  // 报错:价格太低
console.log("customPrice", agent.customPrice);

设计原则验证

  • 代理类和目标类分离,隔离开目标类和使用者
  • 符合开放封闭原则

代理模式 VS 适配器模式

  • 适配器模式:提供一个不同的接口(如不同版本的插头)
  • 代理模式:提供一模一样的接口

代理模式 VS 装饰器模式

  • 装饰器模式:拓展功能,原有功能不变且可直接使用
  • 代理模式:显示原有功能,但经过限制或阉割之后的
(0)

相关推荐

  • 关于JQuery引用及基本用法

    在JQuery文件中下载,并将其引入html文件.在使用jQuery之前,我们需要到jQuery的官方网站:"https://jquery.com/download/" 把下载好的 ...

  • 设计模式(十三)——代理模式

    设计模式(十三)——代理模式

  • 代理模式

    为什么要学习代理模式?因为这就是Spring AOP的底层机制![Spring AOP 和 Spring MVC] 1.什么是代理模式 代理模式的定义:为其他对象提供一种代理以控制对这个对象的访问.在 ...

  • PHP设计模式之代理模式

    PHP设计模式之代理模式 代理人这个职业在中国有另外一个称呼,房产经济人.保险经济人,其实这个职业在国外都是叫做房产代理或者保险代理.顾名思义,就是由他们来帮我们处理这些对我们大部分人来说都比较生疏的 ...

  • [PHP小课堂]PHP设计模式之代理模式

    [PHP小课堂]PHP设计模式之代理模式 关注公众号:[硬核项目经理]获取最新文章 添加微信/QQ好友:[DarkMatterZyCoder/149844827]免费得PHP.项目管理学习资料

  • 如何运用EDIUS代理模式

    当我们导入高清的长视频到EDIUS中时,播放就会出现卡顿的现象,播放速度就会变慢,这样就给后期剪辑工作带来了一些麻烦,这时候我们就会想办法解决这个问.其实,在EDIUS视频编辑软件中代理模式就可以很好 ...

  • 特斯拉直营模式能否持续?一文读懂直营、授权、代理模式前世今生|4s店|上海大众

    2021-04-27 19:15:18 来源: 电车人 2021年3月27-28日,电车人学院"雄鹰计划"总裁班(黄埔二期)第4次课·市场与产品专题在北京万集科技举办,来自整车.核 ...

  • 小米之家疯狂扩张千店同开,直营模式PK友商代理模式,谁会赢?

    2020年小米交出了满意的业绩,小米10出货量超500万台,成为继华为之后又一个开始站稳高端市场的中国厂商.小米在经历了三年的起伏之后,2020年终于开始发力,在线上小米重新拿回市场份额第一,线下小米 ...

  • 结构型模式之代理模式

    在有些情况下,一个客户不能或者不想直接访问另一个对象,这时需要找一个中介帮忙完成某项任务,这个中介就是代理对象. 定义与特点 由于某些原因需要给某对象提供一个代理以控制对该对象的访问.这时,访问对象不 ...

  • 无废话设计模式(11)结构型模式--代理模式

    0-前言 代理模式定义:为其他对象提供一种代理以控制对这个对象的访问. 1-实现 1-1.简单UML图: 1-2.代码实现 //1.抽象父类 abstract class Actor { public ...

  • 【设计模式】牛掰格拉斯的代理模式

    代理的本质 无论任何时候,只要谈到设计模式,大脑中一定要蹦出这四个字"活学活用". 要想对某个事物做到活学活用,必须要对它足够了解,甚至要剖析到本质才行. 总是会有些人说,我干嘛要 ...