# 设计模式——代理模式

提到代理,我们可能想到的是代理人。在生活中代理人最多的可能就是明星了,每个明星都有自己的代理人,我们找明星合作通常都是先接触代理人,然后才接触明星。也就是说这个代理人是在我们和明星之间进行了一次拦截,筛选出符合见明星的人。其实代理模式在开发中也是这样,只不过这里代理的是对象,而不是明星,通过为对象提供一个代理,用来控制对这个对象的访问。

# 代理模式定义:

为对象提供一个代理,用来控制对这个对象的访问。

下面以具体代码举例:比如公司的个人信息的访问:

let person = {
  id = '1',
  name = '刘亦菲',
  age:30
}
console.log(person.name)

上面定义了一个包含个人信息的对象person,如果没有进行代理,那么可以直接通过person.xx进行访问。但是,事实上我们不希望个人信息被查看,只有本人能够进行查看和修改。那么这时候我们可以对对象的访问添加代理。 具体代码如下:

let info = (function(){
  let person = {
    id:1,
    name:'刘亦菲',
    age:24,
    job:'teacher'
  }

  return function({id}){
    //代理对象
    let handle = {
      get:function(target,key){
        if(key === 'age'){
          if(id === 1){
            return Reflect.get(target,key)
          }else{
            throw new Error('您没有权限查看该信息')
          }
        }
      },
      set:function(target,key,value){
        if(id === 1){
          return Reflect.set(target,key,value)
        }else{
          throw new Error('您没有权限修改个人信息')
        }
      }
    }
    return new Proxy(person,handle)
  }
})()

let star = info({id:1})
console.log(star.age)
star.age = 30;
console.log(star.age)

通过使用new Proxy(target,handle)来进行代理。其中target为被代理对象,handle为代理对象或者说拦截对象。在handle中我们通过定义getset函数来进行拦截,只有id1的人才能查看自己的个人信息。这就是代理模式。

# 代理模式的应用场景:

上面的例子只是简单的代理对象的访问,其实代理更多的时候是用于控制开销很大的对象的访问。比如,一个创建实例开销很大的访问,它会把创建实例放到方法被调用的时候(也就是真正需要被用到的时候),因为如果整个程序运行期间都没有用到这个对象,那么就不需要创建它,这样可以大大节省资源。比如图片的延迟加载,我们并不需要一开始就加载所有的图片,而是使用一张loading图片来代替它们,只有在真正需要展示这张图片的时候,再替代掉src即可。

# 代理模式的总结:

归功接底代理模式就是控制对对象的访问,无论是拦截访问,还是延迟访问都是对对象访问的控制罢了。如果你要访问一个对象,但是你不想马上访问,或者不想直接访问那么这都是代理模式。