JS设计模式---(代理模式篇)

代理模式,简单的理解就是有一个代理人的角色,会去帮你谈事情。相当于明星身边的经纪人所做的事情一样。

举个例子,js中的事件委托机制想必大家都不陌生。没错,事件委托机制也是一个代理模式。

<ul id="ul">
    <li>来了老妹</li>
    <li class='li'>来了老弟</li>
    <li>来了媳妇</li>
    <li>来了老公</li>
</ul>

//js
 var li  = document.getElementsByTagName("li")
 console.log(li);
 for(let i=0;i<li.length;i++){
      li[i].onclick = function(){
      this.style.background = "skyblue"
      }
  }

没用事件委托之前都是给每个li标签添加点击事件,但是这样会增加内存损耗

document.getElementById('list').addEventListener('click', 	function (e) {
	// 兼容性处理
	var event = e || window.event;
	var target = event.target || event.srcElement;
	// 判断是否匹配目标元素
	//多种写法,看自己适合哪种用哪种
	//if (e.target.className=="li") {
	//if (e.target.matches("ul>li")) {
	if (target.nodeName.toLocaleLowerCase() === 'li') {
	  console.log('li: ', target.innerHTML);
	}
});

这里li需要做的事情,让ul代理去做了,实现了代理机制,减少了内存消耗。

vue3的proxy想必大家也是熟悉的,这也是一个代理模式

//用法
const p = new Proxy(target, handler)

target :要使用 Proxy 包装的目标对象(可以是任何类型的对象,包括原生数组,函数,甚至另一个代理)。

handler :一个通常以函数作为属性的对象,各属性中的函数分别定义了在执行各种操作时,代理 p 的行为。

对于社交软件大家应该都是挺熟悉的
首先,自己会去填个人信息,然后就可以去软件中的广场找帅哥靓女聊天了。

// 靓妹
const girl = {
  // 姓名
  name: '小美',
  // 自我介绍
  instruction: 'xxx'
  // 年龄
  age: 24,
  // 职业
  career: 'teacher',
  // 手机号
  phone: 123456,
  //照片
  photo:'xxx'
}

但是点击他们的信息就会发现,很多资料是看不到的。为什么呢?大家资料必填项都填了吧。主要是因为做了限制需要去开通vip和实名认证

// 普通私密信息
const baseInfo = ['age', 'career']
// 最私密信息
const privateInfo = ['photo', 'phone']

// 用户(自己)对象实例
const user = {
    ...(必填项的个人信息)
    isValidated: true, //实名认证
    isVIP: false,//vip
}

// 社交软件tantan登场了
const tantan= new Proxy(girl, {
  get: function(girl, key) {
      if(baseInfo.indexOf(key)!==-1 && !user.isValidated) {
          alert('您还没有完成验证哦')
          return
      }
      
      //...(此处省略其它有的没的各种校验逻辑)
    
      // 此处我们认为只有验证过的用户才可以购买VIP
      if(user.isValidated && privateInfo.indexOf(key) && !user.isVIP) {
          alert('只有VIP才可以查看该信息哦')
          return
      }
  }
})

以上主要是 getter 层面的拦截。假设我们还允许会员间互送礼物,每个会员可以告知软件自己愿意接受的礼物的价格下限,我们还可以作 setter 层面的拦截。:

// 规定礼物的数据结构由type和value组成
const present = {
    type: '荧光棒',
    value: 1,
}

// 为用户增开presents字段存储礼物
const girl = {
  // 姓名
  name: '小美',
  // 自我介绍
  instruction: 'xxx'
  // 年龄
  age: 24,
  // 职业
  career: 'teacher',
  // 手机号
  phone: 123456,
  //照片
  photo:'xxx',
  // 礼物数组
  presents: [],
  // 拒收50块以下的礼物
  bottomValue: 50,
  // 记录最近一次收到的礼物
  lastPresent: present,
}

// tantan推出了小礼物功能
const tantan= new Proxy(girl, {
  get: function(girl, key) {
    if(baseInfo.indexOf(key)!==-1 && !user.isValidated) {
        alert('您还没有完成验证哦')
        return
    }
    
    //...(此处省略其它有的没的各种校验逻辑)
  
    // 此处我们认为只有验证过的用户才可以购买VIP
    if(user.isValidated && privateInfo.indexOf(key)!==-1 && !user.isVIP) {
        alert('只有VIP才可以查看该信息哦')
        return
    }
  }
  
  set: function(girl, key, val) {
 
    // 最近一次送来的礼物会尝试赋值给lastPresent字段
    if(key === 'lastPresent') {
      if(val.value < girl.bottomValue) {
          alert('sorry,您的礼物被拒收了')
          return
      }
    
      // 如果没有拒收,则赋值成功,同时并入presents数组
      girl.lastPresent = val
      girl.presents = [...girl.presents, val]
    }
  }
 
})

代理模式的用处:我们遵循面向对象设计原则的单一职责原则:一个对象应该尽可能少的承担职责,最好是一个,如果承担职责过多,会提高代码的耦合度,从而导致脆弱和低内聚的设计。当变化发生,设计可能遭到意外破坏,即使实现同样需求可以将代码封装到一个函数中,但是最好的处理措施是引入代理模式

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值