博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
JS设计模式初识(三)-代理模式
阅读量:7084 次
发布时间:2019-06-28

本文共 3734 字,大约阅读时间需要 12 分钟。

一、定义

代理模式是为一个对象提供一个代用品或占位符,以便控制对它的访问。

3.1 基本概念

代理模式是一种非常有意义的模式,在生活中可以找到很多代理模式的场景。比如,明星都 有经纪人作为代理。如果想请明星来办一场商业演出,只能联系他的经纪人。经纪人会把商业演 出的细节和报酬都谈好之后,再把合同交给明星签。代理模式的关键是,当客户不方便直接访问一个对象或者不满足需要的时候,提供一个替身对象来控制对这个对象的访问,客户实际上访问的是替身对象。替身对象对请求做出一些处理之后,再把请求转交给本体对象。

图: 3-1 不使用代理模式

图 3-2 使用代理模式

3.2 简单代理模式

3.2.1 基本代理实现

小明同学喜欢大A, 他们之间有一个共同大朋友B,于是小明同学通过代理B给大A女神送?,以提高自己追求女神的成功率。B会在大A心情愉悦的时候给A送花。

function Flower() {}    const xiaoMing = {        sendFlower: function(target) {            target.recivedFlower(flower);        }    }    // 大A女神    const A = {        recivedFlower: (flower) => {            console.log('A recived => ',flower);        },        listenGoodMoon: (fn) => { //十秒后心情变好            setTimeout(() => {                fn && fn();            }, 5000);        }    }    // 代理B 监听A心情变好的时候送出花    const B = {        recivedFlower: (flower) => {            A.listenGoodMoon(() => {                const flower = new Flower(); // 延迟创建对象                A.recivedFlower(flower);            })        }    }    xiaoMing.sendFlower(B);复制代码
3.2.2 保护代理和虚拟代理
  • 保护代理: 代理 B 可以帮助A过滤掉一些请求,比如送花的人中年龄太大的或者没有宝马的,这种请求就可以直接在代理 B 处被拒绝掉。这种代理叫作保护代理。A 和 B 一个充当白脸,一个充当黑脸。白脸 A 继续保持良好的女神形象,不希望直接拒绝任何人,于是找了黑脸 B 来控制对 A 的访问。

  • 虚拟代理: new Flower 也是一个代价昂贵的操作, 那么我们可以把 new Flower 的操作交给代理 B 去执行,代理 B 会选择在 A 心情好时再执行 new Flower,这是代理模式的另一种形式,叫作虚拟代理。虚拟代理把一些开销很大的对象,延迟到 真正需要它的时候才去创建。

3.3 虚拟代理实现惰性加载图片

// 虚拟代理实现惰性加载图片 , 先展示展位图    const myImage = (function(){        const imgNode = document.getElementById('img');        document.body.appendChild(imgNode);        return {            setSrc: (src) => {                imgNode.src = src;            }        }    })();    const proxyImage = (function(){        const img = new Image();        img.onload = function() {            myImage.setSrc(this.src);        }        return {            setSrc: function(src) {                myImage.setSrc('file://xxx.png'); // 占位图                img.src = src;            }        }    })();    proxyImage.setSrc('https://timgsa.baidu.com/timg?image&quality=80&size=b9999_10000&sec=1560084344566&di=1715e9c36a3ea72ebadea7f3dece0d50&imgtype=0&src=http%3A%2F%2F02.imgmini.eastday.com%2Fmobile%2F20170909%2F20170909181904_24a9ff37f7c98886769a9e85f15b7d60_1.jpeg');复制代码

现在我们通过 proxyImage 间接地访问 MyImage。proxyImage 控制了客户对 MyImage 的访问,并 且在此过程中加入一些额外的操作,比如在真正的图片加载好之前,先把 img 节点的 src 设置为 一张本地的 loading 图片。

3.4 单一职责原则

单一职责原则指的是,就一个类(通常也包括对象和函数等)而言,应该仅有一个引起它变 化的原因。如果一个对象承担了多项职责,就意味着这个对象将变得巨大,引起它变化的原因可 能会有多个。面向对象设计鼓励将行为分布到细粒度的对象之中,如果一个对象承担的职责过多,等于把这些职责耦合到了一起,这种耦合会导致脆弱和低内聚的设计。当变化发生时,设计可能会遭到意外的破坏。

3.5 缓存代理

3.5.1 基本实现
// 缓存代理    const mult = function() {        let result = 1;        for (let i=0; i
3.5.2 优化代码
// 优化代码    const mult = (...args) => {        return args.reduce((rs, item) => rs * item);    }    const proxyMult = (function() {        const cache = {};        return (...args) => {            const argsStr = args.join(',');            let result = cache[argsStr];            return caches[argsStr] = result ? result : mult(...args);        };    })();复制代码
3.5.3 衍生: 使用高阶函数来创建缓存代理工厂
// 使用高阶函数来创建缓存代理工厂    const mult = (...args) => args.reduce((rs, item) => rs * item);    const sum = (...args) => args.reduce((rs, item) => rs + item);    // 高阶函数    const createProxyFactory = (fn = ()=>{}) => {        const cache = {};        return (...args) => {            const argsStr = args.join(',');            const result = !isEmpty(cache) && cache[argsStr];            return cache[argsStr] = result ? result : fn(...args);        }    }    const proxyMult = createProxyFactory(mult);    proxyMult(1,2,3,5);复制代码

二、总结

代理模式包括许多小分类,在 JavaScript 开发中最常用的是虚拟代理和缓存代理。虽然代理 模式非常有用,但我们在编写业务代码的时候,往往不需要去预先猜测是否需要使用代理模式。 当真正发现不方便直接访问某个对象的时候,再编写代理也不迟。

转载于:https://juejin.im/post/5cfccc1ce51d4556f76e8065

你可能感兴趣的文章
ubuntu下 wine如何解决 rtx乱码问题
查看>>
第5章分布式系统模式 Singleton
查看>>
清明节回安徽扫墓的行程和时间
查看>>
解决centos4不能使用yum的方法
查看>>
祝福51CTO学院成立2周年
查看>>
免费ip共享库
查看>>
GMT时间转换
查看>>
项目中UX设计1到2的设计提升总结
查看>>
JS(JavaScript)的初了解5(更新中···)
查看>>
Hadoop Yarn源码 - day1
查看>>
导出csv用excel打开后数字不用科学计数法显示(0123456显示123456)
查看>>
ssm框架,出现xxx不能加载,或者bean不能加载时的解决方案之一
查看>>
springmvc+mybatis多数据源配置,AOP注解动态切换数据源
查看>>
Centos 6.8 系统下安装RabbitMQ方法
查看>>
SQL Server不能启动
查看>>
Educational Codeforces Round 65 (Rated for Div. 2) C. News Distribution
查看>>
[转] 如何写好.babelrc?Babel的presets和plugins配置解析
查看>>
The JVM Architecture Explained
查看>>
输入框禁止表情
查看>>
最大乘积(大佬的代码)
查看>>