一,概述
代理模式是Android中比较常用的设计模式,不仅在系统源码中经常出现,平常使用的各大开源框架也时常见到它的身影。
代理模式又叫委托模式,其实就是在使用者和被使用者之间,增加一个第三方,使用者不再直接与被使用者打交道,而是一切操作都交与这个第三方来实现。例如甲要租房,会找个中介,中介帮助甲去找房、看房和交租金,甲只要结果就行了。
代理模式的组成:
Abstract Subject:抽象主题。声明真实主题和代理主题共同的接口
Real Subject:真实主题。真实的对象,需要被代理主题引用
Proxy Subject:代理主题。因为ProxySubject引用了RealSubject,并且实现了跟RealSubject一样的接口,所以ProxySubject可以操作RealSubject,还可以提供一些附加操作
代理模式的分类:
按照代码一般可分为静态代理和动态代理
基于场景可分为:
1,Virtual Proxy:虚拟代理。其实就是通过代理的模式对消耗资源比较大的对象做了一个延迟加载,就是什么时候用到这个对象才去创建它
2,Remote Proxy:远程代理。是比较经典的应用了,类似于C/S模式(主要拦截并控制远程方法的调用,做代理防火墙之类的)
3,Smart Reference Proxy:智能引用代理。可以给引用的对象提供一些额外的操作,例如实现里面中介Searching和Prepare contract的动作
4,Access Proxy;保护代理。可以控制一个对象的访问,必要时候提供一系列的权限管理
5,Copy-on-write Proxy:写时拷贝代理。其实是Virtual Proxy的分支,提供了拷贝大对象的时候只有在对象真正变化后才会进行拷贝的操作(延迟拷贝)
二,示例
以概述中举的租房子的例子,来实现代理模式。
1,一般静态代理
根据租房子的找房子、看房子、交租金这三个需求,定义一个接口,也就是抽象主题。
public interface IHouse {
void searchHouse();
void lookHouse();
void priceHouse();
}
然后定义房子实体类,实现抽象接口,也就是真实主题。
public class House implements IHouse {
private static final String TAG = "House";
@Override
public void searchHouse() {
Log.i(TAG, "searchHouse...");
}
@Override
public void lookHouse() {
Log.i(TAG, "lookHouse...");
}
@Override
public void priceHouse() {
Log.i(TAG, "priceHouse...");
}
}
定义房子代理,就是传说中的中介,同样实现抽象接口,并持有真实房子的引用,也就是代理主题。
public class ProxyHouse implements IHouse {
private House mHouse;
public ProxyHouse(House house) {
mHouse = house;
}
@Override
public void searchHouse() {
mHouse.searchHouse();
}
@Override
public void lookHouse() {
mHouse.lookHouse();
}
@Override
public void priceHouse() {
mHouse.priceHouse();
}
}
至此准备工作就完成了,让我们捋一下:我们作为客户想要租房子,不用自己去找房子看房子,而是找一个代理帮我们完成,也就是ProxyHouse,代理持有房子的引用,拥有房子的一切功能和信息,所以我们无需直接跟房子打交道,一切事务交给代理就行了。下面调用测试:
House house = new House();
ProxyHouse proxyHouse = new ProxyHouse(house);
proxyHouse.searchHouse();
proxyHouse.lookHouse();
proxyHouse.priceHouse();
运行结果如下:
2,动态代理
顾名思义,动态代理,代理的对象肯定不能像上述静态代理一样是固定的,而是可以代理多种对象,这也是动态代理更常用的主要原因。
动态代理不需要定义代理类,需要一个实现了InvocationHandler的类,通过反射的方式调用功能。
public class ProxyHandler implements InvocationHandler {
private Object object;
public ProxyHandler(Object object) {
this.object = object;
}
@Override
public Object invoke(Object o, Method method, Object[] objects) throws Throwable {
Object result = method.invoke(object, objects);
return result;
}
}
调用方式:
House house = new House();
ProxyHandler proxyHandler = new ProxyHandler(house);
ClassLoader classLoader = house.getClass().getClassLoader();
IHouse iHouse = (IHouse) Proxy.newProxyInstance(classLoader, new Class[]{IHouse.class}, proxyHandler);
iHouse.searchHouse();
iHouse.lookHouse();
iHouse.priceHouse();
结果和静态代理一样。