结构型设计模式——代理模式

274 阅读2分钟

1、介绍

代理模式:为其他对象提供一种代理一控制对这个对象的访问。

在代理模式中,有四个角色

  • Subject: 抽象主题类,声明主题类与代理的公共接口方法
  • RealSubject: 主题类,代理类所代表的主题,通过代理类调用主题类
  • Proxy: 代理类,持有对主题类的引用
  • Client: 客户端

其中代理模式分为静态代理和动态代理,静态代理是在运行前就已经存在代理类的class文件,动态代理在代码运行时通过反射动态生成代理类对象。

2、实现(静态)

2.1、抽象主题类

抽象主题类含有主题类和代理类共同的接口和方法。

public interface Subject{
    void play();
}

2.2、主题类

主题类实现抽象主题类的方法。

publice class RealSubject implement Subject{
    @Override
    public void play(){
    ...
    }
}

2.3、代理类

代理类同样实现抽象主题类的方法,并且在代理类内部持有主题类。

public class Proxy implement Subject{
    private Subject s;
    public Proxy(Subject s){
        this.s=s;
    }
    @Override
    public void play(){
        s.play();
    }
}

2.4、客户端调用

Subject realSubject =new RealSubject();
Subject proxy =new Proxy(realSubject);
proxy.play();

3、实现(动态)

动态代理会由代码运行时动态决定代理谁,Java有动态代理接口InvocationHandler,实现这个接口并重写invoke方法。

3.1、创建动态代理类

public class DynamicProxy implements InvocationHandler{
    private Object obj;
    public DynamicProxy(Object obj){
        this.obj=obj;
    }
    @Override 
    public Object invoke(Object proxy,Method method,Object[] args)throws Throwable{
        Object result=method.invoke(obj,args);
        if(method.getName().equals("play")){
            ...
        }
        reutrn result;
    }
}

在这个动态代理类中声明一个Object引用,引用指向代理类,调用代理类的方法在invoke中执行。

3.2、客户端调用

//首先创建主题类即RealSubject
Subject realSubject =new RealSubject();

//创建动态代理dynamicProxy
DynamicProxy dynamicProxy =new DynamicProxy(realSubject);

//创建RealSubject的ClassLoader
ClassLoader classLoader=realSubject.getClass().getClassLoader();

//动态创建代理类proxy
Subject proxy=(Subject)Proxy.newProxyInstance(classLoader,new Class[] {Subject.class},dynamicProxy);

//调用代理类中的方法
proxy.play();

在动态代理中通过newProxyInstance来得到动态代理类,之后在调用动态代理类的过程中会使用invoke方法。

4、其他

优点

  • 主题类实现实际的业务逻辑,无需关注其他部分
  • 主题类具有高拓展性,实现了公共接口,在主题类发生变化是代理类无需修改

缺点

  • 增加了代理对象,因此会造成处理的速度变慢
  • 增加了代码复杂度