代理模式(
Proxy Pattern
)也称为委托模式。本质就是为某对象提供一种代理以控制对这个对象的访问。
场景
很不幸你碰到了一个老板不给你发工资,你会请个律师帮你打官司。很显然你对打官司一窍不通,因此只能通过代理对象去间接打官司。你作为委托对象,律师作为代理对象,都需要实现相同的接口或继承相同的抽象类。
UML类图
简单实现
- 诉讼接口类
/**
* 诉讼接口类
*/
public interface ILawsuit {
//诉讼方法
void lawsuit();
}
- 诉讼人
/**
* 诉讼人(委托类)
*/
public class Person implements ILawsuit {
@Override
public void lawsuit() {
System.out.print("我要诉讼");
}
}
- 代理律师
/**
* 代理律师(代理对象)
*/
public class Laywer implements ILawsuit {
private ILawsuit mLawsuit; //持有被代理者的引用
public Laywer(ILawsuit lawsuit) {
this.mLawsuit = lawsuit;
}
@Override
public void lawsuit() {
mLawsuit.lawsuit();
}
}
- 客户端调用
public void main(){
Person mPerson = new Person();
//构造一个代理律师,并将被代理者作为构造参数传递进去
ILawsuit iLawsuit = new Laywer(mPerson);
iLawsuit.lawsuit();
}
显然,一个律师可以帮很多人打官司。其实我们这个代理类可以代理多个诉讼者,只要诉讼实现ILawsuit
接口,并将其作为构造参数传递进去。
代理模式大致分为两种:一是静态代理,二是动态代理。
上述示例即为静态代理,代码运行前代理类的class编译文件已经存在了。而动态代理则相反,它是通过反射机制动态地生成代理对象。Java给我们提供了动态代理接口InvocationHandler,实现此接口需要重写invoke方法。
延伸
回想《AIDL浅析》一文中类图(如上),正是使用了代理模式。
IMyAidlInterface.Stub
作为委托类,IMyAidlInterface.Stub.Proxy
作为代理类,都实现了IMyAidlInterface
接口。而Stub
是个抽象类,并不处理过多的具体逻辑,真实的逻辑还是在RemoteService
中继承了IMyAidlInterface.Stub
的子类MyBinder
里。客户端调用Stub.asInterface
方法将MyBinder
对象作为参数传递,返回一个AIDL
对象,执行add
方法。而真实的流程是,asInterface
方法首先会在本地查找AIDL
对象,如果没有则实例化Proxy
,MyBinder
作为参数,执行add
方法。显然Proxy
代理了Stub
的add
方法。
而追溯到底层,就需要了解Binder跨进程通信机制了。