设计模式梳理之代理模式

梳理总是由易到难,代理模式又是不难理解的一种模式,因为做前端的小伙伴都是常用代理,那今天梳理一下所谓的代理模式

什么是代理模式

代理模式我们十分常见,不光说我们生活中所见的所谓的代理模式,经纪人,秘书,律师,包括投资经理,都属于是代理模式的体现,再看我们代码中实际体现的,host,服务器代理i请求,vue双向绑定的核心,VPN工具,这些都属于代理,那么代理身上有什么样的共性呢,那就是为一个对象找一个替代对象,以便对原对象进行访问,至于为什么要有一个替代对象,我们从上述的例子出发来看,为什么有经纪人秘书投资精力,host.VPN工具这样的替代对象出现,简单来讲就是原对象不能完成某些功能,通过代理的拦截来替他完成,以便对象能正常的使用,有时候会觉得代理就是扩展一样,其实代理的核心我感觉是拦截

  • 拦截
    为什么说代理的核心是拦截,因为要替代原有对象做一些事情的时候,必须要拦截到原本对原有对象所做的事情, 或者说需要原有对象所做的事情,那拦截就是必不可少的了,有些形似代理模式的逻辑,并没有所谓的get和set拦截,只是给对象封装了一个方法,调用对象更改数据等操作的时候为了不改变原有对象,直接调用了封装的逻辑,这个封装的逻辑其实我感觉也算代理模式:举个栗子

例子如下,从思想出发来解释,缩减到极致的例子,并不代表实际运用是如此

//程序员吃饭

//餐厅
restaurant{
	'西红柿鸡蛋盖饭':15,
	'尖椒肉丝盖饭':18,
	'红烧牛肉面':25
}


//现在程序员来吃饭了
restaurant['红烧牛肉面']
//然后得到价钱发现是25,然后购买

程序员直接到餐厅点餐拿到饭食,并没有经过任何中间途径,那这么看来就不是代理

//餐厅规则的添加,周六尖椒肉丝贵两块
funtion proxyRest(name){
	let data = new Date().getDay()
	if( data === 6 && name === '尖椒肉丝盖饭' ){
		return restaurant[name]+2
	} else{
		return restaurant[name]
	}
}

假设我们摒弃对象本身的代理来说,只从最原始的逻辑出发,那我们就多加了一个这样的方法,以后程序员再吃饭就不再是直接调用餐厅这个对象来获取,而是通过方法来知道要付多少钱,那这个方法就相当于一个代理,访问对象时,会经过代理一层,中间来做判断来做对象的访问,或者说改变一下,变成老板与店长更好理解

//老板经营餐厅
funtion Boss(){
	this.restaurant{
		'西红柿鸡蛋盖饭':15,
		'尖椒肉丝盖饭':18,
		'红烧牛肉面':25
	}
	return restaurant['红烧牛肉面']
}
//老板代理给店长管理店铺
funtion Boos(){
	return shopowner(name)
}

funtion shopowner(name){
	this.restaurant{
		'西红柿鸡蛋盖饭':15,
		'尖椒肉丝盖饭':18,
		'红烧牛肉面':25
	}
	let data = new Date().getDay()
	if( data === 6 && name === '尖椒肉丝盖饭' ){
		return restaurant[name]+2
	} else{
		return restaurant[name]
	}
}

想直接找老板买东西,老板说,想要啥, 我让店长去安排,店长就去进行判断进行返回,这就是工作被店长代理了

Proxy

有人会讲,这样是不是太过于麻烦,当然代理不是所有时刻都适合使用的,所有的设计模式都不是适用于所有的地方的,我们说会代理模式,有一个非常好用且完全遵循代理模式的东西就是Proxy,Proxy在vue3.0的梳理中已经讲过了,我们主要说Proxy对代理模式的使用

关于ES6的Proxy,概念是说:用于修改某些操作的默认行为,等同于在语言层面做出修改,所以属于一种“元编程”(meta programming),即对编程语言进行编程。很好理解,从语言基础层面去做出修改,为什么这样讲,我们来看

var objProxy = new Proxy(obj, {
  get: function (target, propKey, receiver) {
  	.............
  },
  set: function (target, propKey, value, receiver) {
    .............
  }
});

get和set就是属性被取出使用和塞入更改的时候的拦截,es6语法中可以直接去重写这两个方法,来达到拦截的目的,这个也有讲过

  • 验证代理
    1.对数据做出验证
    这个不做赘述了就,从上述的set方法就可以看出,我们在进行set操作的时候可以进行一系列的逻辑处理,那再set里进行逻辑处理就是验证代理
    还有一个对应的get操作的拦截就是私有属性代理,就是在进行读取数据操作时,做逻辑判断,看是否允许读取数据
//借用网上表单验证代理的代码
const getValidateProxy = (target, validators) => {
  return new Proxy(target, {
    _validators: validators,
    set(target, prop, value) {
      if (value === '') {
        console.error(`"${prop}" is not allowed to be empty`);
        return target[prop] = false;
      }
      const validResult = this._validators[prop](value);
      if(validResult.valid) {
        return Reflect.set(target, prop, value);
      } else {
        console.error(`${validResult.error}`);
        return target[prop] = false;
      }
    }
  })
}
  • 缓存代理
    1.对方法做出代理
//cache看作缓存的储存起来的之前传入的参数和得出计算的数据的键值对
var objProxy = new Proxy(fn, {
 apply(target, context, args) {
      const argsString = args.join(' ');
      if (cache.has(argsString)) {
        // 如果有缓存,直接返回缓存数据
        return cache.get(argsString);
      }
      const result = fn(...args);
      //没有缓存的话储存进缓存中且返回计算结果
      cache.set(argsString, result);
      return result;
    }
});

这样的好处就是,有些极其复杂的计算逻辑,就可以用缓存的方法来减少实际调用计算逻辑,要说能不能每次调用方法前都自己去调用一下缓存,然后在方法里每次计算也都加上这个逻辑,可以,就是不优雅,所以可以看出,所有的设计模式都是为了省事为了逻辑清晰

  • 6
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值