一、静态代理模式
角色分析
- 抽象角色:一般使用接口或抽象类来解决
- 真实角色:被代理的角色
- 代理角色:代理真实角色,一般会有附属操作
- 客户:访问代理对象的人
老套租房例子
- 租房是抽象角色
public interface Rent {
void rent();
}
- 房东是真实角色,房东现在只要管自己租房别的什么都不用管
public class Host implements Rent{
@Override
public void rent() {
System.out.println("host rent");
}
}
- 中介是代理角色
public class Proxy implements Rent{
private Host host;
public Proxy(Host host)
{
this.host = host;
}
@Override
public void rent() {
view();
host.rent();
signContract();
fee();
}
//看房
public void view()
{
System.out.println("proxy help to view the house");
}
//签合同
public void signContract()
{
System.out.println("sign contract");
}
//收中介费
public void fee()
{
System.out.println("get proxy fee");
}
}
- 而你作为客户去找中介租房,永远见不到房东
public class Client {
public static void main(String[] args) {
//房东要租房子
Host host = new Host();
//代理:中介帮房东租房子,但代理角色会有附属操作
Proxy proxy = new Proxy(host);
//你不用面对房东,直接找中介就可以
proxy.rent();
}
}
静态代理模式的优点
- 使得真实角色处理的业务更加纯粹,不再关注一些公共的事情
- 公共业务由代理来完成,实现业务的分工
- 公共业务发生扩展时变得更加集中和方便管理,比如要新加个装修房子功能,只要在中介代理类中修改代码即可,而不需要改变房东真实角色的代码
静态代理模式的缺点
- 多了代理类,而且一个真实角色就会产生一个代理类,工作量变大,开发效率降低。而动态代理在静态代理的基础上解决了这个问题
二、动态代理模式
- 动态代理和静态代理的真实角色一样
- 动态代理的代理类是动态生成的,而不是我们直接写的
- 与动态代理相关的两个类:
- Proxy:生成动态代理类实例
- InvocationHandler:调用处理程序返回结果
还是租房的例子
- 租房接口(传个参数,带个返回值)
public interface Rent {
boolean rent(String name);
}
- 真实角色房东
public class Host implements Rent{
@Override
public boolean rent(String name) {
System.out.println(name+" rent");
return true;
}
}
- 实现InvocationHandler接口
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
public class ProxyInvovationHandler implements InvocationHandler{
//被代理的接口
private Object obj;
public void setRent(Object obj) {
this.obj = obj;
}
//生产得到代理类
public Object getProxy()
{
return Proxy.newProxyInstance(this.getClass().getClassLoader(), obj.getClass().getInterfaces() , this);
}
//处理代理实例,并返回结果
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
//加入日志业务
//这里通过反射获取了被调用方法的方法名
log(method);
//这里执行调用方法,原理也是反射
Object result = method.invoke(obj, args);
return result;
}
//日志业务
public void log(Method method)
{
System.out.println(method.getName() + "方法被执行");
}
}
- 客户找代理租房
public class Client {
public static void main(String[] args) {
//真实角色
Host host = new Host();
//代理角色,现在还没有
ProxyInvovationHandler pih = new ProxyInvovationHandler();
//通过调用程序处理角色来处理我们要调用的接口对象
pih.setRent(host);
//得到代理类实例
Rent proxy = (Rent) pih.getProxy();
//代理处理业务
boolean re = proxy.rent("jerry");
System.out.println(re);
}
}
输出:
rent方法被执行
jerry rent
true
动态代理的优点
- 所有静态代理的优点
- 一个动态代理一般代理某一类业务,并且可以代理多个接口