1

说到代理模式大家一定不会模式在ES6中就有代理的语法糖,代理模式是一种结构型设计模式,其实从ES6Proxy中可以明确的感觉的出,一个客户不能或者不像直接访问另一个对象,这是需要找一个中介帮忙完成某项任务,这个中介帮忙完成某项任务,这个中介就是代理对象。

举一个生活中的栗子,春节也即将临近,大家在购买回家的车票的是偶不一定要去火车站去买火车票,可以通过网上的一些平台或者去车票代售点去购买车票。这些网上的平台网站和代售车票的售票点都是代理模式的一种。在软件设计中,使用代理模式的例子也有很多,例如,要访问的远程对象比较大,下载可能需要很长很长的时间,我这个时候我们需要通过某个媒介去下载完成这步操作。

什么是代理模式

代理模式:是程序设计中的一种设计模式,为其他对象提供一种代理以控制对这个对象的访问。在某些情况下,一个对象不适合或者不能直接引用另一个对象,而代理对象可以在客户端和目标对象之间起到中介的作用。 —— 节选自百度百科

代理模式分为两种模式,一种是静态代理,一种是动态代理,如果是静态代理的的话,需要修改Proxy类中构造函数的参数类型或者创建一个新的Proxy代理完成,因为对于静态代理来说,一旦代码谷底,则代理类就固定下来了,而通过动态代理,可以运行时,通过反射来创建代理类。其实这些也是代理模式的设计思想,通过代理的方式避免暴露被代理对象或者说代理不容易被取得的对象,这样就满足了开闭原则。

静态代理模式

静态代理模式在使用时,需要定义接口或者父类,被代理对象与代理对象一起实现相同的接口或者时继承相同的父类。

静态代理优缺点

静态代理类只能为特定的接口服务。如想要为多个接口服务则需要建立很多个代理类。

优点
  1. 在不修改目标对象的功能前提下,能通过代理对象对目标功能扩展
缺点
  1. 因为代理对象需要与目标对象实现一样的接口,所以会出现很多的代理类
  2. 一旦接口增加方法,目标对象与代理对象都要维护
  3. 增加代理类之后明显会增加处理时间,拖慢处理时间
静态代理示例

静态代理的主要角色如下:

  1. 抽象主题:是抽象类也可以是接口
  2. 具体主题角色:是业务逻辑的具体执行者
  3. 代理类:负责对真实角色的应用,把所有抽象主题类定义的方法限制委托给真实主题角色实现,并且在真实主题角色处理完毕前后做预处理和善后处理工作

类图如下所示:

image

代码示例:

// 静态代理
interface Subject {
    doOperation() : void;
}

class RealSubject implements Subject {
    public doOperation() {
        console.log('我是RealSubject类,正在执行');
    }
}

class MyProxy implements Subject {
    private target : Subject;
    constructor(realSubject : Subject) {
        this.target = realSubject;
    }

    public doOperation() {
        console.log('我是代理类');
        this.target.doOperation();
    }
}

function main() {
    const realSubject : Subject = new RealSubject();
    const myProxy : Subject = new MyProxy(realSubject);
    myProxy.doOperation();
}

main();

动态代理模式

代理对象不需要实现接口,但是目标对象要实现接口,否则不能用动态代理。其中代理对象的生成,动态的在内存中构建代理对象。

动态代理优缺点

动态代理本质上仍然是代理,代理类并不是在代码中定义的,而是在运行时根据我们在代码中的行为动态生成的。

优点

代理对象不需要实现接口

缺点

增加代理对象之后明显会增加处理时间,拖慢处理时间

动态代理示例

动态代理的主要角色如下:

  1. 代理工厂类:生产主要代理类的工厂
  2. 抽象主题:是抽象类也可以是接口
  3. 具体主题角色:是业务逻辑的具体执行者

类图如下所示:

image

代码示例:

// 动态代理
interface Subject {
    doOperation() : void;
}

class RealSubject implements Subject {
    constructor() {}

    public doOperation() : void {
        console.log('我是RealSubject类,正在执行');
    }
}

class ProxyFactory {
    private target : any;
    constructor(target : any) {
        this.target = target;
    }

    public getProxyInstance() : any {
        return new Proxy(this.target, {
            get: (target, propKey) => {
                // 做的一些拦截处理
                return target[propKey];
            }
        });
    }
}

function main() {
    const target : Subject = new RealSubject();
    const proxyInstance:Subject<Subject> = new ProxyFactory(target);
    const instance = proxyInstance.getProxyInstance();
    proxyInstance.doOperation();
}

main();

总结

代理模式分为静态代理和动态袋理,静态代理类需要自己编写代码,动态代理,代理类通过代理工厂创建,不管是静态代理还是动态代理,代理与被代理都要实现两样接口,它们的实质是面向接口编程。

静态代理和动态代理的区别是在于要不要开发者自己定义Proxy类。动态代理通过Proxy动态生成proxy class,但是它也指定了一个InvocationHandler的实现类。代理模式本质上的目的是为了增强现有代码的功能。


Aaron
4k 声望6.1k 粉丝

Easy life, happy elimination of bugs.