Design pattern--代理模式

Design pattern–代理模式

代理模式是常用的设计模式之一,在retrofit2源码分析过程中,看到了动态代理的使用,非常精妙,有必要深入理解下。代理模式有两种,静态代理和动态代理。

静态代理

这里写图片描述

代理(Proxy)是一种设计模式,即通过代理对象访问目标对象,好处是:可以在目标对象实现的基础上,增强额外的功能操作,即扩展目标对象的功能.看一个例子

// Subject.java
public interface Subject {
  void operation();
}

// RealSubject.java
public class RealSubject implements Subject{
  @Override public void operation() {
    System.out.println("operation by RealSubject");
  }
}

// ProxySub.java
public class ProxySub implements Subject{
  Subject subject;
  public ProxySub(Subject subject) {
    this.subject = subject;
  }
  @Override public void operation() {
    System.out.println("do other things");
    subject.operation();
  }
}

// MainActivity.java
public class MainActivity extends AppCompatActivity {

  @Override protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    ProxySub sub = new ProxySub(new RealSubject());
    sub.operation();
  }
}

ProxySub是一个代理类,目标对象是RealSubject,最终调用的是RealSubject#operation方法,但是调用RealSubject#operation前后可以做些额外的操作。

静态代理总结:

1.可以做到在不修改目标对象的功能前提下,对目标功能扩展.

2.缺点:
因为代理对象需要与目标对象实现一样的接口,所以会有很多代理类. 同时,一旦接口增加方法,目标对象与代理对象都要维护.

如何解决静态代理中的缺点呢?答案是使用动态代理


动态代理

通过InvocationHandler来完成动态代理

// ProxySubject.java
public class ProxySubject implements InvocationHandler{
  Subject subject;
  public ProxySubject(Subject subject) {
    this.subject = subject;
  }

  @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
    System.out.println("method->" + method.getName());
    return method.invoke(subject, args);
  }
}

// MainActivity.java
final Subject subject = new RealSubject();
ProxySubject proxy = new ProxySubject(subject);
Subject sub = (Subject) Proxy.newProxyInstance(subject.getClass().getClassLoader(),
    subject.getClass().getInterfaces(), proxy);
sub.operation();

运行一下:

06-03 16:05:31.683 2173-2173/com.rico.proxy I/System.out: method->operation
06-03 16:05:31.683 2173-2173/com.rico.proxy I/System.out: operation by RealSubject

调用过程大致是:newProxyInstance得到一个动态生成的代理类 $Proxy0,这个类继承了Proxy并且实现了Subject接口,所以调用$Proxy0#operation方法,实际上调用的是super.h.invoke(this, , ),也就是父类Proxy的h的invoke方法,也就是ProxySubject的invoke方法,然后通过反射method.invoke(subject, args);调用RealSubject#operation接口,有点绕,但是基本上说清楚了

查看源码发现$Proxy0正式调用getProxyClass0构建出来的,通过反射得到所有的构造方法,然后调用newInstance(cons, h);动态构建$Proxy0,传入的h正式我们ProxySubject实例

public static Object newProxyInstance(ClassLoader loader,
                                          Class<?>[] interfaces,
                                          InvocationHandler h)
        throws IllegalArgumentException
    {
        if (h == null) {
            throw new NullPointerException();
        }

        /*
         * Look up or generate the designated proxy class.
         */
        Class<?> cl = getProxyClass0(loader, interfaces);

        /*
         * Invoke its constructor with the designated invocation handler.
         */
        try {
            final Constructor<?> cons = cl.getConstructor(constructorParams);
            return newInstance(cons, h);
        } catch (NoSuchMethodException e) {
            throw new InternalError(e.toString());
        }
    }

下面看下$Proxy0的源码

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.lang.reflect.UndeclaredThrowableException;

public final class $Proxy0 extends Proxy implements Manager {

private static Method m1;
private static Method m0;
private static Method m3;
private static Method m2;

static {
   try {
    m1 = Class.forName("java.lang.Object").getMethod("equals",
      new Class[] { Class.forName("java.lang.Object") });
    m0 = Class.forName("java.lang.Object").getMethod("hashCode",
      new Class[0]);
    m3 = Class.forName("com.ml.test.Manager").getMethod("modify",
      new Class[0]);
    m2 = Class.forName("java.lang.Object").getMethod("toString",
      new Class[0]);
   } catch (NoSuchMethodException nosuchmethodexception) {
    throw new NoSuchMethodError(nosuchmethodexception.getMessage());
   } catch (ClassNotFoundException classnotfoundexception) {
    throw new NoClassDefFoundError(classnotfoundexception.getMessage());
   }
}

public $Proxy0(InvocationHandler invocationhandler) {
   super(invocationhandler);
}

@Override
public final boolean equals(Object obj) {
   try {
    return ((Boolean) super.h.invoke(this, m1, new Object[] { obj }))
      .booleanValue();
   } catch (Throwable throwable) {
    throw new UndeclaredThrowableException(throwable);
   }
}

@Override
public final int hashCode() {
   try {
    return ((Integer) super.h.invoke(this, m0, null)).intValue();
   } catch (Throwable throwable) {
    throw new UndeclaredThrowableException(throwable);
   }
}

public final void operation() {
   try {
    super.h.invoke(this, m3, null);
    return;
   } catch (Error e) {
   } catch (Throwable throwable) {
    throw new UndeclaredThrowableException(throwable);
   }
}

@Override
public final String toString() {
   try {
    return (String) super.h.invoke(this, m2, null);
   } catch (Throwable throwable) {
    throw new UndeclaredThrowableException(throwable);
   }
}
}

代理模式就分析这么多了,以上!

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

chengyuan9160

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值