摘要:文章系列设计模式单例模式设计模式策略模式设计模式代理模式概念代理模式是为一个对象提供一个代用品或占位符,以便控制对它的访问。
前言
本系列文章主要根据《JavaScript设计模式与开发实践》整理而来,其中会加入了一些自己的思考。希望对大家有所帮助。
文章系列js设计模式--单例模式
js设计模式--策略模式
js设计模式--代理模式
概念代理模式是为一个对象提供一个代用品或占位符,以便控制对它的访问。
UML类图 场景比如,明星都有经纪人作为代理。如果想请明星来办一场商业演出,只能联系他的经纪人。经纪人会把商业演出的细节和报酬都谈好之后,再把合同交给明星签。
分类 保护代理于控制不同权限的对象对目标对象的访问,如上面明星经纪人的例子虚拟代理
把一些开销很大的对象,延迟到真正需要它的时候才去创建。 如短时间内发起很多个http请求,我们可以用虚拟代理实现一定时间内的请求统一发送优缺点 优点
1. 可以保护对象 2. 优化性能,减少开销很大的对象 3. 缓存结果例子 图片预加载 加载一张图片
var myImage = (function () { var imgNode = document.createElement("img"); document.body.appendChild(imgNode); return { setSrc: function (src) { imgNode.src = src; } } })(); myImage.setSrc("https://segmentfault.com/img/bVbmvnB?w=573&h=158");
想象一下,如果我们的图片很大,用户就会看到页面很长一段时间是空白
我们可以想到的改进是图片加载完成之前都展示loading图片
var myImage = (function () { var imgNode = document.createElement("img"); document.body.appendChild(imgNode); var img = new Image() img.onload = () => { // 模拟图片加载 setTimeout(() => { imgNode.src = img.src }, 1000) } return { setSrc: function (src) { img.src = src imgNode.src = "https://content.igola.com/static/WEB/images/other/loading-searching.gif"; } } })(); myImage.setSrc("https://segmentfault.com/img/bVbmvnB?w=573&h=158");
这段代码违背了单一职责原则,这个对象同时承担了加载图片和预加载图片两个职责
同时也违背了开放封闭原则,如果我们以后不需要预加载图片了,那我们不得不修改整个对象
var myImage = (function () { var imgNode = document.createElement("img"); document.body.appendChild(imgNode); return { setSrc: function (src) { imgNode.src = src } } })(); var proxyImage = (function() { var img = new Image() img.onload = function() { myImage.setSrc(img.src) } return { setSrc: function (src) { img.src = src myImage.setSrc("https://content.igola.com/static/WEB/images/other/loading-searching.gif") } } })() proxyImage.setSrc("https://segmentfault.com/img/bVbmvnB?w=573&h=158");
注意:我们的代理和本体接口要保持一致性,如上面proxyImage和myImage都返回一个包含setSrc方法的对象。居于这点我们写代理的时候也有迹可循。
虚拟代理合并HTTP请求 简单的实现1 2 3 4 5 6 7 8 9
缺点很明显:每点一次就发送一次http请求
改进缓存代理-计算乘积 粗糙的实现1 2 3 4 5 6 7 8 9
var mult = function () { console.log("开始计算乘积"); var a = 1; for (var i = 0, l = arguments.length; i < l; i++) { a = a * arguments[i]; } return a; }; mult(2, 3); // 输出:6 mult(2, 3, 4); // 输出:24改进
var mult = function () { console.log("开始计算乘积"); var a = 1; for (var i = 0, l = arguments.length; i < l; i++) { a = a * arguments[i]; } return a; }; // mult(2, 3); // 输出:6 // mult(2, 3, 4); // 输出:24 var proxyMult = (function() { var cache = {} return function () { let id = Array.prototype.join.call(arguments, ",") if (cache[id]) { return cache[id] } else { return cache[id] = mult.apply(this, arguments) } } })() proxyMult(2, 3); // 输出:6 proxyMult(2, 3); // 输出:6
我们现在希望加法也能够缓存
再改进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 plus = function () { console.log("开始计算和"); var a = 0; for (var i = 0, l = arguments.length; i < l; i++) { a = a + arguments[i]; } return a; }; // mult(2, 3); // 输出:6 // mult(2, 3, 4); // 输出:24 var createProxyFactory = function (fn) { var cache = {} return function () { let id = Array.prototype.join.call(arguments, ",") if (cache[id]) { return cache[id] } else { return cache[id] = fn.apply(this, arguments) } } } var proxyMult = createProxyFactory(mult), proxyPlus = createProxyFactory(plus); proxyMult(1, 2, 3, 4) // 输出:24 proxyMult(1, 2, 3, 4) // 输出:24 proxyPlus(1, 2, 3, 4) // 输出:10 proxyPlus(1, 2, 3, 4) // 输出:10es6的代理模式 基于类实现
class Car { drive() { return "driving"; }; } class CarProxy { constructor(driver) { this.driver = driver; } drive() { return ( this.driver.age < 18) ? "too young to drive" : new Car().drive(); }; } class Driver { constructor(age) { this.age = age; } }基于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)
文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。
转载请注明本文地址:https://www.ucloud.cn/yun/100651.html
摘要:代理设计模式代理模式为其他对象提供一种代理以控制对这个对象的访问。代理模式是常见的设计模式之一是指不直接调用实际的对象,而是通过代理对象,来间接的调用实际的对象。对象类定义了代理对象所代表的目标对象。 代理设计模式 代理模式:为其他对象提供一种代理以控制对这个对象的访问。代理模式是常见的设计模式之一,是指不直接调用实际的对象,而是通过代理对象,来间接的调用实际的对象。为什么要采用这种间...
摘要:保护代理和虚拟代理保护代理当有许多需求要向某对象发出一些请求时,可以设置保护代理,通过一些条件判断对请求进行过滤。虚拟代理在程序中可以能有一些代价昂贵的操作。而虚拟代理是最常用的一种代理模式。 代理模式 代理模式是为一个对象提供一个代用品或占位符,以便控制对它的访问。 保护代理和虚拟代理 保护代理:当有许多需求要向某对象发出一些请求时,可以设置保护代理,通过一些条件判断对请求进行过滤。...
摘要:什么是代理模式代理模式,类似于明星的经纪人,想要拜访明星,需要先通过经纪人的沟通。不同于装饰器,那种动态加载一个对象,可以说在代理模式当中,代理是早已既定的。又称单一功能原则,面向对象五个基本原则之一。 什么是代理模式 代理模式,类似于明星的经纪人,想要拜访明星,需要先通过经纪人的沟通。而在JS当中,如果想访问一个类,需要通过另一个类来间接访问 。不同于装饰器,那种动态加载一个对象,可...
摘要:代理模式的定义为其他对象提供一种代理以控制对这个对象的访问。代理模式在客户端和目标对象之间起到一个中介作用,这样可以起到保护目标对象的作用。代理对象也可以对目标对象调用之前进行其他操作。 代理模式的定义:为其他对象提供一种代理以控制对这个对象的访问。在某些情况下,一个对象不适合或者不能直接引用另一个对象,而代理对象可以在客户端和目标对象之间起到中介的作用。 原文链接 虚拟代理 虚拟代理...
摘要:代理模式原文地址更多设计模式系列教程更多免费教程博主按每天一个设计模式旨在初步领会设计模式的精髓,目前采用靠这吃饭和纯粹喜欢两种语言实现。代理模式优缺点代理模式有高度解耦对象保护易修改等优点。 代理模式·原文地址 更多《设计模式系列教程》 更多免费教程 博主按:《每天一个设计模式》旨在初步领会设计模式的精髓,目前采用javascript(_靠这吃饭_)和python(_纯粹喜欢_)...
摘要:代理模式原文地址更多设计模式系列教程更多免费教程博主按每天一个设计模式旨在初步领会设计模式的精髓,目前采用靠这吃饭和纯粹喜欢两种语言实现。代理模式优缺点代理模式有高度解耦对象保护易修改等优点。 代理模式·原文地址 更多《设计模式系列教程》 更多免费教程 博主按:《每天一个设计模式》旨在初步领会设计模式的精髓,目前采用javascript(_靠这吃饭_)和python(_纯粹喜欢_)...
阅读 1639·2021-09-26 10:00
阅读 2908·2021-09-06 15:00
阅读 3510·2021-09-04 16:40
阅读 2276·2019-08-30 15:44
阅读 679·2019-08-30 10:59
阅读 1862·2019-08-29 18:34
阅读 3580·2019-08-29 15:42
阅读 2273·2019-08-29 15:36