代理的结构

代理模式的最基本形式就是对访问进行控制。代理对象和另一个对象实现的是同样的接口。代理对象只是节制对本体的访问。
代理对象不会在另一个对象上添加或修改方法,也不会简化对象的接口,所有对方法的调用都会被传递给本体。

虚拟代理

用于控制对那种创建开销很大的本体的访问。他会把本体的实例化推迟到有方法被调用的时候。
代理对象具有与本体类实例对象的相同的方法,想操作本体类实例对象必须先通过代理对象,从而实现对本体类实例对象的控制。

创建虚拟代理的通用模式

  1. 先创建一个动态代理类的壳体及initialize和checkInitialization两个方法
  2. 创建派生子类
  3. 设置子类的class属性为本体类
  4. 设置触发实例化条件
// 抽象类
function Dynamic() {this.args = arguments;this.initialized = false;if(typeof this.class !== 'function '){throw new Error('err');}let that = this;for(let key in this.class.prototype) {if(typeof this.class.prototype[key] !== 'function'){continue;}(function (methodName){that[methodName] = function () {if(!that.initialized){return;}return that.subject[methodName].apply(that.subject, arguments);}})(key);}
}
Dynamic.prototype = {_initialize(){this.subject = {};this.class.call(this.subject, this.args);this.subject.__proto__ = this.class.prototype;this.interval = setInterval(()=>{this._checkInitialized();},100);},_checkInitialized(){if(this._isInitialized()){clearInterval(this.interval);this.isInitialized = true;}},_isInitialized(){throw new Error('error');}
}// 本体类
function TestClass() {}
TestClass.prototype.add = function (){return 1 + 1;
}
TestClass.prototype.sub = fuunction () {return 2 - 1;
}// 对本体类的代理
function TestProxy() {this.class = TestClass;// 触发初始化的条件document.getElementById('test-link').addEventListener('click', ()=>{this._initialize();});TestProxy.superclass.constructor.apply(this, arguments);
}TestProxy.prototype._isInitialized = function (){if(this.subject){return true;}
}// 继承函数
function extend(subClass, supClass){function F(){}F.prototype = supClass.prototype;subClass.prototype = new F();subClass.prototype.constructor = subClass;subClass.superclass = supClass.prototype;
}
extend(TestProxy, DynamicProxy);

示例:图片预加载

let myImage = (function (src) {let node = document.createElement('img');document.body.appendChild(node);return {setSrc(src){node.src = src;}}
})();let proxyImg = (function (){let img = new Image();img.onload = function (){myImage.setSrc(this.src);}return {setSrc(src){myImage.setSrc('');img.src=src;}}
})();

示例:合并http请求

当有多个多选框,用户点击多选框进行上传文件时,当用户点击的过快,会导致服务器压力过大,此时需要通过虚拟代理,减少在某一时刻发送的请求数量。

let syncrequest = function (ids) {console.log('开始同步文件', ids);
}let proxSync = (function () {let cache = [],timer;return function (id) {cache.push(id);if (timer) {return;}timer = setTimeout(() => {syncrequest(cache.join(','));clearTimeout(timer);timer = null;}, 2000);}
})();let checkbox = document.getElementsByTagName('input');
for(let i = 0, c; c = checkbox[i++];){c.onclick = function(){if(this.checked === true){proxSync(this.id);}}
}

远程代理

远程代理用于访问另一个环境中的对象。
这种方式很难照搬到JavaScript中:

  1. 通常JavaScript运行环境不能长时间存在
  2. JavaScript中无法建立到另一个环境的套接字连接以访问其变量空间

控制对其他语言中的本体的访问。这种本体可能是Web服务资源,也可能是PHP对象,很难说你所使用的是什么模式。

安全代理

安全代理:用来控制真实对象的访问权限,即满足条件的可以访问,不满足条件的不能访问


class Order {constructor(productName, productCount, orderUserName) {this.productName = productName;this.productCount = productCount;this.orderUser = orderUserName;}// 获取订单中产品的名称getProductName() {return this.productName;}// 设置订单中产品的名称setProductName(productName) {this.productName = productName;}// 获取订单的用户getOrderUserName() {return this.orderUserName;}// 设置订单的用户setOrderUserName(orderUserName) {this.orderUserName = orderUserName;}// 获取产品数量getProductCount() {return this.oproductCount;}// 设置产品数量setProductCount(productCount) {this.productCount = productCount;}}class ProxyObject {constructor(realObject) {this.realObject = realObject;}// 获取订单中产品的名称getProductName() {if (userName === this.realObject.orderUserName) {return this.realObject.productName;}}// 设置订单中产品的名称setProductName(productName, userName) {if (userName === this.realObject.orderUserName) {this.realObject.productName = productName;}}// 获取订单的用户getOrderUserName() {if (userName === this.realObject.orderUserName) {return this.realObject.orderUserName;}}// 设置订单的用户setOrderUserName(orderUserName, userName) {if (userName === this.realObject.orderUserName) {this.realObject.orderUserName = orderUserName;}}// 获取产品数量getProductCount() {return this.realObject.productCount;}// 设置产品数量setProductCount(productCount, userName) {if (userName === this.realObject.orderUserName) {this.realObject.productCount = productCount;}}}let order = new Order('西瓜', 1, 'wang');let subject = new ProxyObject(order);let productCount = subject.getProductCount(order.orderUserName);console.log(productCount);

缓存代理

缓存代理可以为一些开销大的运算结果提供暂时的存储,在下次运算时,如果传递进来的参数跟之前一致,则可以直接返回前面存储的运算结果

以计算乘积的程序为例,mult()方法用于计算乘积并返回计算后的结果,proxyMult用于把mult()计算后的结果缓存,当有相同的参数时,把参数对应的结果返回,如果没有相同的参数,把参数的乘积计算后缓存然后返回结果。

var mult = function () {console.log('开始计算乘积');var a = 1;for (var i = 0, l = arguments.length; i < l; i++) {a = a * arguments[i];}return a;
};var proxyMult = (function () { var cache = {}; return function () { var args = Array.prototype.join.call(arguments, ', '); if (args in cache) { return cache[args]; } return cache[args] = mult.apply(this, arguments); }
})(); proxyMult(1, 2, 3, 4);
// 输出:24      proxyMult( 1, 2, 3, 4 );
// 输出:24

代理模式的适用场合

虚拟代理是一种优化模式。如果有些类或对象需要使用大量内存保存其数据,而你并不需要在实例化后立即访问这些数据, 或者, 构造函数需要进行大量计算,此时需要使用虚拟代理模式。

优缺点

优点

控制开销较大的对象的创建时机。

缺点

代理可以隐藏大量复杂行为。

javascript设计模式-代理模式相关推荐

  1. JavaScript设计模式系列—模式篇总结(上)

    转载请注明预见才能遇见的博客:http://my.csdn.net/ 原文地址:https://blog.csdn.net/pcaxb/article/details/102517956 JavaSc ...

  2. Python设计模式-代理模式

    Python设计模式-代理模式 基于Python3.5.2,代码如下 #coding:utf-8info_struct = dict() info_struct["addr"] = ...

  3. Java设计模式(代理模式-模板方法模式-命令模式)

    Java设计模式Ⅴ 1.代理模式 1.1 代理模式概述 1.2 静态代理 1.2.1 静态代理概述 1.2.2 代码理解 1.3 动态代理之JDK代理 1.3.1 动态代理之JDK代理概述 1.3.2 ...

  4. 设计模式——代理模式

    设计模式--代理模式 代理(Proxy)是一种设计模式,提供了对目标对象另外的访问方式;即通过代理对象访问目标对象.这样做的好处是:可以在目标对象实现的基础上,增强额外的功能操作,即扩展目标对象的功能 ...

  5. 23种设计模式----------代理模式(一)

    代理模式也叫委托模式. 代理模式定义:对其他对象提供一种代理从而控制对这个对象的访问.就是,代理类 代理 被代理类,来执行被代理类里的方法. 一般情况下,代理模式化有三个角色. 1,抽象的主题类(或者 ...

  6. java设计模式代理模式_Java中的代理设计模式

    java设计模式代理模式 代理对象或代理对象为另一个对象提供占位符,以控制对该对象的访问. 代理充当原始对象的轻量级版本或简化版本. 它支持与原始对象相同的操作,但可以将那些请求委托给原始对象以实现它 ...

  7. 第四章 Caché 设计模式 代理模式

    文章目录 第四章 Caché 设计模式 代理模式 定义 类型 使用场景 优点 缺点 结构图 完整示例 抽象主题类 真实主题类 代理类 对象类 调用 思考 第四章 Caché 设计模式 代理模式 定义 ...

  8. Android常见设计模式——代理模式(Proxy Pattern)(二)

    文章目录 1. 前言 2. 远程代理(Remote Proxy) 3. 后记 1. 前言 在上篇Android常见设计模式--代理模式(Proxy Pattern)中基本上知道了什么是代理模式,以及对 ...

  9. sheng的学习笔记-设计模式-代理模式

    原理图: 代理模式的定义:由于某些原因需要给某对象提供一个代理以控制对该对象的访问.这时,访问对象不适合或者不能直接引用目标对象,代理对象作为访问对象和目标对象之间的中介. 至少在以下集中情况下可以用 ...

最新文章

  1. Nginx学习之二-配置项解析及编程实现
  2. php加密 dll扩展,PHP的openssl加密扩展使用小结(推荐)
  3. python主要用于系统编程_一文带你了解python是什么?能做什么?为什么(附赠40G项目实战+绝版电子书)...
  4. nginx php mysql 部署_Linux+Nginx+Mysql+Php运维部署
  5. dpdk18.11 收发包流程分析
  6. react学习(32)----onref
  7. 事实--思维导图笔记
  8. 使用dbutils对mysql数据库做增删改查的基本操作方法
  9. python爬虫获取下一页url_Python爬虫获取页面所有URL链接过程详解
  10. 9-15 redis-trib构建集群
  11. Windows防火墙添加80端口,解决apache无法访问的问题
  12. CentOS6.5 firefox安装flash插件
  13. WEEK5 周记 作业——差分数组_TT的魔法猫
  14. 每日分享,三款纯jquery移动端日期时间选择插件
  15. WIN10 系统重新安装 WIN7 系统步骤
  16. XMUOJ·纸片选择
  17. 车载服务器作用,穿针引线谈铁路机车车载系统服务器
  18. 码元携带多少比特信息?波特率和比特率的关系?
  19. 百度地图路线规划重新设置起点、终点图标和路线颜色
  20. Python3 遇到\\u开头的编码

热门文章

  1. 解决Qt生成exe错误:无法定位程序输入点
  2. java创意生日快乐_Java,25岁生日快乐!
  3. discuz后台 论坛分类添加英文名称
  4. 什么是跨阻放大器:工作及其应用特性介绍
  5. 赛元单片机SC92F732x系列printf函数构造[以7321为例]
  6. 从游戏设计机制以及玩家心理特征到互联网产品
  7. 1577_AURIX_TC275_MTU中检测控制相关寄存器
  8. 兄弟mfc7220打印没反应_设备操作面板按键无反应
  9. 入手评测 索尼A7R4A怎么样 值得入手吗
  10. 2022.5.29 第八次周报