代理模式

168 阅读2分钟

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

js中常用的两个代理

  1. 虚拟代理
    假设现实中的花价格不菲,导致在程序世界里,new Flower 也是一个代价昂贵的操作,那么我们可以把 new Flower 的操作交给代理 B 去执行,代理 B 会选择在 A 心情好时再执行 new Flower,这是代理模式的另一种形式,叫作虚拟代理。
  2. 缓存代理
    这里主要是通过一个代理来存储方法执行的缓存信息,提高方法的运行效率。

代理和面向对象设计的关系

涉及的两个原则

  1. 单一职责原则
    单一职责原则指的是,就一个类(通常也包括对象和函数等)而言,应该仅有一个引起它变化的原因。
  2. 开放-封闭原则
    开放-封闭原则指的是,软件应该面向拓展开放, 而面向修改封闭。也就是我们在新增功能的时候应该增加代码,而不是修改代码。

在面向对象的程序设计中,大多数情况下,若违反其他任何原则,同时将违反开放—封闭原则。

通过代理模式,在进行对象的编写时,我们可以有一种方式来遵循以上两个原则。

  • 我们可以将核心功能抽离为一个对象,一般而言,核心功能是不会变化的,保证封闭原则。
  • 将其它拓展功能作为代理进行实现,这样可以在不改动核心功能的前提下对我们的功能进行拓展,而在需要移除某些功能时也可以直接在代理上进行操作。保证开放原则。

实现

Java 等语言中,代理和本体都需要显式地实现同一个接口,一方面接口保证了它们会拥有同样的方法,另一方面,面向接口编程迎合依赖倒置原则,通过接口进行向上转型,从而避开编译器的类型检查,代理和本体将来可以被替换使用。

使用高阶函数创建缓存代理

//这里实现的是 cache proxy
const muti = (...arguments) =>{
    return arguments.reduce( (pre, cur) => pre * cur);
}
const plus = (...arguments) => {
    return arguments.reduce( ( pre, cur) => pre + cur) ;
}
/**
 *
 * @param  computionalFunction
 *
 * @returns a proxy for computional function with cache
 *
 * */
const createCacheProxy = function ( fn ) {
    let cache = {};
    return function (){
        let args = Array.prototype.join.call( arguments, ','); // same as hash
        if( args in cache )
        {
            return cache[args];
        }
        return cache[ args ] = fn.apply(this, arguments);
    }
}

let cachedMuti = new createCacheProxy(muti);

console.log(cachedMuti(1,2,3,4));

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