动态代理
讲代理模式不讲动态代理简直是耍流氓。相比 必知必会的设计模式8 里提到的实现方式,这种实现的特点在于只有在代码运行时才知道为谁做代理,这种实现涉及到反射技术,代码阅读起来没那么直观。不过虽说实现起来和之前的方式相差较大,设计结构上实际没什么改变大的改变。
不过在实现上,Java 提供了现成的一套工具,InvocationHandler 用于动态代理类的实现接口,也就是说实现这个接口的类就被看做是动态代理类。那普通类还是普通类,需要实现功能接口。InvocationHandler 接口里只有一个方法 invoke,简单理解就是通过这个方法能最终控制普通类对象的方法调用。
另外我们还需要一个 Proxy 类,这个也是 Java 提供的,它通过 newProxyInstance 方法可以创建一个代理类实例(但其实就是功能接口类型实例),所以如果要使用动态代理,写法也比较固定,
//IFunction 表示功能接口
//这里用了匿名内部类来实现了 InvocationHandler 的 invoke 方法
//当然也可以定义一个类来实现 InvocationHandler 接口,再传入类对象
IFunction ifun = (IFunction) Proxy.newProxyInstance(IFunction.class.getClassLoader(), new Class<?>[]{IFunction.class}, new InvocationHandler() {
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
//这里是默认的实现,如果要结合业务逻辑,要再改动改动
//例如可以看看 Retrofit 类的代码,它里面就用到了动态代理
return method.invoke(this, args);
}
});
可见动态代理我们省去的其实是代理类的实现。那动态代理有什么用途呢?最典型的,在 Android 中也是可实践的就是 AOP(面向切面编程,这是一个概念,就像面向对象编程),通过切面方式可以实现在想要的地方增加逻辑处理,而尽可能不去改动原有逻辑。我尝试过在项目里用 AOP 的 AspectJ(这个是具体的实现技术) 来实现权限的动态申请,不得不说确实方便很多。
与策略模式的对比
了解了代理模式,再回头来看下 策略模式 发现有相似点,假如我们让 Context 上下文类也实现策略接口,那这不就是代理模式么。可见模式间的转换就在某个小细节上,模式与模式间也是有一定的联系的。
参考内容
「设计模式之禅(第 2 版)」
「Android 源码设计模式解析与实战」
网友评论