一天一个设计分享 (一天一个运营小技巧)

(六)代理模式

代理模式(Proxy Pattern)指为其他对象提供一种代理,以控制这个对象的访问。当无法或者不想直接引用某个对象时,或者访问某个对象存在困难时,可以通过代理对象来访问。代理模式的两个主要目标:1,保护目标对象;2,增强目标对象。

1,代理模式的设计原则

1,抽象主题(ISubject):负责声明真实主题与代理类的共同接口方法;

2,真实主题(RealSubject):即被代理类;

3,代理主题(Proxy):即代理类,在内部持有真实主题的引用,因此具有代理权。

一天一个运营小技巧,一天一个商业模式

2,简单例子

代理有两种,静态代理和动态代理之分。我们先来举个静态代理的例子,比如父亲给儿子相亲。

public interface IPerson {
  void findGirls();
}
public class Father implements IPerson {
//   对儿子的引用
  private Son son;
  public Father(Son son){
    this.son = son;
   }
  @Override
  public void findGirls() {
    System.out.println("帮儿子相亲!");
    son.findGirls();
    System.out.println("相亲成功!");
   }
}
public class Son implements IPerson {
  @Override
  public void findGirls() {
    System.out.println("相亲!");
   }
}
public class Client {
  public static void main(String[] args) {
    Father father = new Father(new Son());
    father.findGirls();
   }
}

也就是说,父亲只能帮儿子相亲,不能帮别人了(这就是静态代理的模式)。这对以后的发展肯定是不行的,我们需要让专业的人做专业的事情,比如媒婆(动态代理)。我们使用jdk自带的代理方式实现:

public class JDKMeipo implements InvocationHandler {
//   接口型的被代理对象的引用
  private IPerson target;
  public IPerson getInstance(IPerson target){
    this.target = target;
    Class<? extends IPerson> clazz = target.getClass();
    return (IPerson) Proxy.newProxyInstance(clazz.getClassLoader(),clazz.getInterfaces(),this);
   }

  @Override
  public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
//     业务处理
    before();
    Object result = method.invoke(this.target,args);
    after();
    return result;
   }
  public void before(){
    System.out.println("媒婆安排相亲!");
   }
  public void after(){
    System.out.println("成功!");
   }
}

动态代理的实现及机制包括jdk本身的通过反射实现动态代理,还有就是CGLib库提供的动态代理方式。

//待补充

CGLib和JDK动态代理的对比分析:

1,jdk动态代理实现了被代理对象的接口,CGLib动态代理继承了被代理对象;

2,jdk动态代理和CGLib都是在运行期间生成字节码,jdk动态代理直接写Class字节码,CGLib使用ASM框架写字节码,CGLib更复杂,生成代理类效率低。

3,jdk通过反射机制实现动态代理,CGLib通过FastClass机制直接调用,执行效率高。

3,代理模式的点评

代理模式能将代理对象与真实被调用目标对象分离,解耦,扩展性好;可以实现保护目标和增强目标对象的作用。不足是导致实现复杂,在目标对象中增加代理可能会导致处理请求变慢。