代理模式,相似于明星的经纪人,想要拜访明星,须要先经过经纪人的沟通。而在JS当中,若是想访问一个类,须要经过另外一个类来间接访问 。不一样于装饰器,那种动态加载一个对象,能够说在代理模式当中,代理是早已既定的。ajax
再拿最常遇到的收快递这一个社会行为举例吧。
很早以前,咱们收发快递都是直接和快递员交互的,例如:
而如今,加入了代理以后,能够经过第三方替咱们接收快递,即:
这是生活当中一个很是常见的例子,能够说代理的存在,大大的便利了“我”这个对象。下面就让咱们在程序中看看代理是如何方便“我”的。缓存
程序作这样一件事,即根据不一样的快递类型,来进行不一样的操做(执行不一样的函数),那么在没有引进代理以前,写法多是这个样子。
无代理:异步
class getDelivery { constructor() { } gets(a) { let fn1 = () => { setTimeout(() => { //some fns of fn1 console.log(`获取快递有:${a}`) }, 1000) } let fn2 = () => { setTimeout(() => { //some fns of fn2 console.log(`获取快递有:${a}`) }, 2000) } let fn3 = () => { setTimeout(() => { //some fns of fn3 console.log(`获取快递有:${a}`) }, 3000) } let deliver = {'中通': fn1, 'EMS': fn2, '顺丰': fn3}[name]; return deliver(); } } getDelivery.prototype.proxyGets('中通')
定义一个类,上面的gets函数去判断不一样的快递类型,而后去执行相对应的操做。函数
如今,当咱们引入代理模式以后,代码多是这样的:
代理:spa
class getDelivery { constructor() { } gets(a) { console.log(`获取快递有:${a}`) } } class proxy extends getDelivery { constructor() { super(); } proxyGets(name) { let fn1 = () => { setTimeout(() => { //some fns of fn1 super.gets('中通快递') }, 1000) } let fn2 = () => { setTimeout(() => { //some fns of fn2 super.gets('EMS') }, 2000) } let fn3 = () => { setTimeout(() => { //some fns of fn3 super.gets('顺丰') }, 3000) } let deliver = {'中通': fn1, 'EMS': fn2, '顺丰': fn3}[name]; return deliver(); } } proxy.prototype.proxyGets('中通')
(ps:本代码仅用于代理模式的示例,每次调用函数从新声明fn1等方法是不对的)
ok,这两种方法都会获得这样的结果:
然后者在代码上还多了一些,但为何这里仍是推荐使用后面这种模式来写代码呢?prototype
首先介绍一个面向对象设计原则,单一职责原则。设计
又称单一功能原则,面向对象五个基本原则(SOLID)之一。它规定一个类应该只有一个发生变化的缘由。所谓职责是指类变化的缘由。若是一个类有多于一个的动机被改变,那么这个类就具备多于一个的职责。而单一职责原则就是指一个类或者模块应该有且只有一个改变的缘由。代理
而在本例中,咱们并不关心是什么快递,关心的只是接到快递触发的结果,或者说接到快递后,执行的任务才是getDelivery 这个类的核心,至于中间的过程,应该交给专门处理他的类来判别。code
第二个原则:开放封闭原则对象
开放封闭原则(OCP,Open Closed Principle)是全部面向对象原则的核心。软件设计自己所追求的目标就是封装变化、下降耦合,而开放封闭原则正是对这一目标的最直接体现。其余的设计原则,不少时候是为实现这一目标服务的,例如以Liskov替换原则实现最佳的、正确的继承层次,就能保证不会违反开放封闭原则。
还以接收快递为例,好比有一天,接收快递的形势变了,或者说,根本不须要判断是什么快递,能够随时接收,那么proxy 这个类其实就没有用了,此时咱们能够直接调用getDelivery这个类。可是,若是以第一种写法的话,那就是无路可退了,只能去原对象中去删掉相对应的逻辑。当代码复杂程度变高的话,高耦合的程序,会让人很是恶心。
代理模式,在实践当中还能够应用于缓存ajax异步数据,惰性加载等等方面,本文不详细讲解,仅做抛砖引玉的入门参考。