结构型设计模式 代理模式
分类
- 静态代理:运行之前代理类的 class 编译文件已经存在
- 动态代理:通过反射动态的生成代理者对象。(在执行阶段才知道代理谁) InvocationHandler(动态代理接口)
public interface InvocationHandler {
//通过 invoke 方法来调用具体的被代理方法,也就是真实方法。
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable;
}
模式结构
代理模式包含如下角色:
- Subject: 抽象主题角色
- Proxy: 代理主题角色
-
RealSubject: 真实主题角色
示例
小民以前在公司上班就遇到老板拖欠工资的情况,这种情况小民可以通过法律途径来维护自己的利益,于是小民选择了走法律途径解决该纠纷,那么不可避免的要请一个律师来为自己的诉讼代理人,我们将诉讼的流程抽象在一个接口类中。
1,静态代理
1. 诉讼接口类,抽象主题角色
public interface ILaysuit {
void submit(); //提交申请
void burden(); //进行举报
void defend(); //开始辩护
void finish(); //诉讼完成
}
2. 具体诉讼人,真实主题角色
public class Xiaomin implements ILaysuit{
@Override
public void submit() {
System.out.println("老板拖欠工资");
}
@Override
public void burden() {
System.out.println("这是合同书和去年的银行流水号");
}
@Override
public void defend() {
System.out.println("证据确凿,无可厚非");
}
@Override
public void finish() {
System.out.println("诉讼成功,老板结算拖欠工资");
}
}
3. 代理律师,代理主题角色
public class Lawyer implements ILaysuit{
//持有一个具体被代理者的引用
private ILaysuit mLawsuit;
public Lawyer(ILaysuit mLawsuit) {
this.mLawsuit = mLawsuit;
}
@Override
public void submit() {
mLawsuit.submit();
}
@Override
public void burden() {
mLawsuit.burden();
}
@Override
public void defend() {
mLawsuit.defend();
}
@Override
public void finish() {
mLawsuit.finish();
}
}
4.客户端调用
public class Client {
public static void main(String[] args) {
ILaysuit mLawyer = new Lawyer(new Xiaomin());
mLawyer.submit();
mLawyer.burden();
mLawyer.defend();
mLawyer.finish();
}
}
结果很简单,就不给出了。
静态代理如上述示例,代理者的代码由程序员自己或通过一些自动化工具生成固定的代码在对其编译,也就是
** 静态代理在我们的代码运行之前代理类的 class 编译文件就存在了。
而动态代理,通过反射机制在运行阶段动态生成代理者对象,在code阶段我们压根不知道代理谁,代理谁将在执行阶段决定。
**
2,动态代理
1. 动态代理类
public class DynamicProxy implements InvocationHandler{
private Object obj; //被代理对象的引用
public DynamicProxy(Object obj) {
this.obj = obj;
}
/**
* proxy:被代理对象
*/
@Override
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable {
/**
* 通过 invoke 方法调用具体的被代理方法,也就是真实方法
*/
Object result = method.invoke(obj, args);
return result;
}
}
2. 修改后的客户端
public class Client {
public static void main(String[] args) {
//构造小明
ILaysuit xiaomin = new Xiaomin();
//构造一个动态代理
InvocationHandler proxy = new DynamicProxy(xiaomin);
/**
* 构造代理律师
* xiaomin.getClass().getInterfaces() 同 new Class[]{ILaysuit.class}
*/
ILaysuit lawyer = (ILaysuit) Proxy.newProxyInstance(xiaomin.getClass().getClassLoader()
, xiaomin.getClass().getInterfaces(), proxy);
lawyer.submit("老板拖欠工资");
lawyer.burden("这是合同书和去年的银行流水号");
lawyer.defend("证据确凿,无可厚非");
lawyer.finish("诉讼成功,老板结算拖欠工资");
}
}
拓展
Android源码中的代理实现
1.抽象主题
public interface IActivityManager extends IInterface {}
2.代理类及真实主题
a.真实主题
public abstract class ActivityManagerNative extends Binder implements IActivityManager{}
实现: public final class ActivityManagerService extends ActivityManagerNative
implements Watchdog.Monitor, BatteryStatsImpl.BatteryCallback {}
b.代理类
class ActivityManagerProxy implements IActivityManager{
public ActivityManagerProxy(IBinder remote) { //将真实主题传入
mRemote = remote;
}
...
}
- IActivityManager 抽象主题
- ActivityManagerNative 是个抽象类,其实现是ActivityManagerService,所以 ActivityManagerService 才是真正的真实主题,
- ActivityManagerProxy 代理主题
类似的 Binder 跨进程通信机制与AIDL里面都是这种原理,充满了代理模式的影子,ok!
后记
- 《Android源码设计模式,实战与解析》