javascript设计模式-代理模式
代理的结构
代理模式的最基本形式就是对访问进行控制。代理对象和另一个对象实现的是同样的接口。代理对象只是节制对本体的访问。
代理对象不会在另一个对象上添加或修改方法,也不会简化对象的接口,所有对方法的调用都会被传递给本体。
虚拟代理
用于控制对那种创建开销很大的本体的访问。他会把本体的实例化推迟到有方法被调用的时候。
代理对象具有与本体类实例对象的相同的方法,想操作本体类实例对象必须先通过代理对象,从而实现对本体类实例对象的控制。
创建虚拟代理的通用模式
- 先创建一个动态代理类的壳体及initialize和checkInitialization两个方法
- 创建派生子类
- 设置子类的class属性为本体类
- 设置触发实例化条件
// 抽象类
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中:
- 通常JavaScript运行环境不能长时间存在
- 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设计模式-代理模式相关推荐
- JavaScript设计模式系列—模式篇总结(上)
转载请注明预见才能遇见的博客:http://my.csdn.net/ 原文地址:https://blog.csdn.net/pcaxb/article/details/102517956 JavaSc ...
- Python设计模式-代理模式
Python设计模式-代理模式 基于Python3.5.2,代码如下 #coding:utf-8info_struct = dict() info_struct["addr"] = ...
- Java设计模式(代理模式-模板方法模式-命令模式)
Java设计模式Ⅴ 1.代理模式 1.1 代理模式概述 1.2 静态代理 1.2.1 静态代理概述 1.2.2 代码理解 1.3 动态代理之JDK代理 1.3.1 动态代理之JDK代理概述 1.3.2 ...
- 设计模式——代理模式
设计模式--代理模式 代理(Proxy)是一种设计模式,提供了对目标对象另外的访问方式;即通过代理对象访问目标对象.这样做的好处是:可以在目标对象实现的基础上,增强额外的功能操作,即扩展目标对象的功能 ...
- 23种设计模式----------代理模式(一)
代理模式也叫委托模式. 代理模式定义:对其他对象提供一种代理从而控制对这个对象的访问.就是,代理类 代理 被代理类,来执行被代理类里的方法. 一般情况下,代理模式化有三个角色. 1,抽象的主题类(或者 ...
- java设计模式代理模式_Java中的代理设计模式
java设计模式代理模式 代理对象或代理对象为另一个对象提供占位符,以控制对该对象的访问. 代理充当原始对象的轻量级版本或简化版本. 它支持与原始对象相同的操作,但可以将那些请求委托给原始对象以实现它 ...
- 第四章 Caché 设计模式 代理模式
文章目录 第四章 Caché 设计模式 代理模式 定义 类型 使用场景 优点 缺点 结构图 完整示例 抽象主题类 真实主题类 代理类 对象类 调用 思考 第四章 Caché 设计模式 代理模式 定义 ...
- Android常见设计模式——代理模式(Proxy Pattern)(二)
文章目录 1. 前言 2. 远程代理(Remote Proxy) 3. 后记 1. 前言 在上篇Android常见设计模式--代理模式(Proxy Pattern)中基本上知道了什么是代理模式,以及对 ...
- sheng的学习笔记-设计模式-代理模式
原理图: 代理模式的定义:由于某些原因需要给某对象提供一个代理以控制对该对象的访问.这时,访问对象不适合或者不能直接引用目标对象,代理对象作为访问对象和目标对象之间的中介. 至少在以下集中情况下可以用 ...
最新文章
- Nginx学习之二-配置项解析及编程实现
- php加密 dll扩展,PHP的openssl加密扩展使用小结(推荐)
- python主要用于系统编程_一文带你了解python是什么?能做什么?为什么(附赠40G项目实战+绝版电子书)...
- nginx php mysql 部署_Linux+Nginx+Mysql+Php运维部署
- dpdk18.11 收发包流程分析
- react学习(32)----onref
- 事实--思维导图笔记
- 使用dbutils对mysql数据库做增删改查的基本操作方法
- python爬虫获取下一页url_Python爬虫获取页面所有URL链接过程详解
- 9-15 redis-trib构建集群
- Windows防火墙添加80端口,解决apache无法访问的问题
- CentOS6.5 firefox安装flash插件
- WEEK5 周记 作业——差分数组_TT的魔法猫
- 每日分享,三款纯jquery移动端日期时间选择插件
- WIN10 系统重新安装 WIN7 系统步骤
- XMUOJ·纸片选择
- 车载服务器作用,穿针引线谈铁路机车车载系统服务器
- 码元携带多少比特信息?波特率和比特率的关系?
- 百度地图路线规划重新设置起点、终点图标和路线颜色
- Python3 遇到\\u开头的编码
热门文章
- 解决Qt生成exe错误:无法定位程序输入点
- java创意生日快乐_Java,25岁生日快乐!
- discuz后台 论坛分类添加英文名称
- 什么是跨阻放大器:工作及其应用特性介绍
- 赛元单片机SC92F732x系列printf函数构造[以7321为例]
- 从游戏设计机制以及玩家心理特征到互联网产品
- 1577_AURIX_TC275_MTU中检测控制相关寄存器
- 兄弟mfc7220打印没反应_设备操作面板按键无反应
- 入手评测 索尼A7R4A怎么样 值得入手吗
- 2022.5.29 第八次周报