目录
一、定义
为其他对象提供一种代理以控制对这个对象的访问
通用类图如下:
AbstractSubject:抽象主题角色,可以是接口,也可以是抽象类
RealSubject:真实主题角色,被代理角色
Proxy:委托角色类
二、普通代理
前段时间房子到期了,房东直租可遇不可求,于是我找了中介;这里虽然叫做中介,其实是一种典型的代理模式。这里创建一个房东接口作为抽象主题角色,房东类作为真实主题角色,代理类分别如下:
通过代理类带看,满意后签合同入住:
这就是普通代理;我们不用关心房东,带看,签合同,房东全权委托给中介,租客和中介对接就可以了。
三、强制代理
有个租客打了房东的电话想要租房,但是房东不在家,已经全权委托给一个中介,而且只相信这个中介。三个角色稍微改一下:
房东接口ILandLord新增获取代理方法getProxy();房东类增加私有方法hasProxy()判断是否有自己的代理,有代理才能访问。
访问如下:
首先找到房东,此时没有代理,无法进行访问;
租客自己给房东找了个代理,也不行,必须要自己的;
找到了房东的代理,顺利访问。
四、代理定制
代理帮房东处理房子出租的问题,房子出租后,是要收费的。
定义一个代理接口:
代理类同时实现房东接口、代理接口
成功签了合同,房子租出去了,付费吧。
五、动态代理
实现动态代理首先要介绍两个类:
接口类InvocationHandler:
参数proxy为后面的动态代理对象;
参数method为代理对象的方法;
参数args为代理对象方法的参数;
类Proxy,我们常用其中的newProxyInstance方法来实现动态代理:
loader:类加载器;
interfaces:接口类型数组,表示代理对象要实现哪些接口;
h:InvocationHandler对象,表示代理对象调用方法时交给哪一个InvocationHandler实现。
接着上面普通模式的租房案例,现在不想自己找房东代理(中介)了,于是找到了房东代理公司,想看房的时候随时安排一个:
构造函数传入的参数mObject是被代理对象;
在getProxy方法实现动态代理类,传入被代理对象的类加载器,被代理对象的实现接口(也可以是某一个接口或者某一些接口),以及当前实现了InvocationHandler接口的对象;
在invoke方法中,转调了被代理对象的方法,并且当调用的方法是签合同时,实现收费。
主方法访问如下:
六、代理模式的优点
1 职责清晰
被代理对象实现被代理对象的业务逻辑,不用关心其他非本职的业务;
后期的代理如果有附加业务,代理单独实现
2 扩展性高
只要被代理对象实现的接口不发生变化,被代理对象内逻辑无论如果变化,代理类就可以在不用做任何修改的情况下调用被代理对象的实现