代理模式可分为静态代理,动态代理。
1.静态代理:
静态代理的角色分析:
1.真实对象;
2.代理真实对象的对象(代理对象)一般会添加一些附加的操作;
3.真实对象和代理对象抽象出来的公共部分(一般为抽象类或者接口);
4.用户(通过代理对象来调用真实对象的方法)。
静态代理的一个代码案例:
情景模型:你(用户)通过租房中介(代理对象)从房东(真实对象)进行租房的活动。
真实对象(Host)
//真实对象public class Host implements Rent {public void rent() {
System.out.println("Host 租房子啦!");
}
}
代理对象:
//代理对象public class Proxy implements Rent {private Host host;public Proxy(Host host) {this.host = host;
}public void rent() {
lookHouse();
host.rent();
fare();
}//代理对象添加的额外的操作public void lookHouse(){
System.out.println("带你一起去看看房子!");
}public void fare(){
System.out.println("交易结束,请按时付款!");
}
}
抽象接口:
//抽象接口public interface Rent {void rent();
}
测试类:
public class StaticProxy {
@Testpublic void test(){//通过代理对象执行真实对象的方法Proxy proxy = new Proxy(new Host());
proxy.rent();
}
}
总结:
真实对象,代理对象都实现了接口(房东,中介都来完成租房子这个活动),用户最后通过中介完成和房东的交易,其中还包含了自己额外的一些操作。
优点:
可以使真实角色更加纯粹,不用去关注一些公共的事情;
公共的业务由代理来完成,实现业务的分工;
公共业务的要扩展的话,可以更加集中和方便;
缺点:
假如我们的真实角色变得非常多,代理类也会随之增多,工作量变大,开发效率变低!
2.动态代理:
动态代理和静态代理中的角色都是一样的,差别在于:静态代理中代理类是直接写好的(代理类也是实现了接口),而动态代理中代理类是动态生成的。(代理对象的动态生成)
动态代理的实现可分为两类:
基于接口的实现JDK;
基于类:cglib;
(本文中探究基于jdk接口的实现)
1.首先研究两个类:
InvocationHandler:
是由代理实例的调用处理程序实现的接口 。每个代理实例都有一个关联的调用处理程序。 当在代理实例上调用方法时,方法调用将被编码并分派到其调用处理程序的invoke方法。
(这个Proxy的静态方法,可以返回一个代理实例(抽象接口的实例),当前对象的类加载器(this))
2.动态代理的一个实例:
接口:
//接口public interface Rent {void rent();
}
真实对象:
//真实对象public class Host implements Rent {public void rent() {
System.out.println("Host租房la~");
}
}
动态代理动态的生成代理对象:
//动态代理对象,可以动态的生成一个代理类public class DynamicProxy implements InvocationHandler {//代理的是一个接口private Rent rent;public DynamicProxy(Rent rent) {this.rent = rent;
}//获得代理对象public Object getProxy(){return Proxy.newProxyInstance(this.getClass().getClassLoader(), rent.getClass().getInterfaces(), this);
}//写的invoke方法,用户进行调用后,就执行这个方法//就相当于代理类中重写的接口的方法//参数解析: o:代理对象(属性 接口) // method:就是接口中原来定义的方法 // objects:method方法的参数public Object invoke(Object o, Method method, Object[] objects) throws Throwable {
look();
method.invoke(rent,objects);
fare();return null;
}//一些附加操作public void look(){
System.out.println("我们不是黑中介");
}public void fare(){
System.out.println("请交出服务费~");
}
}
测试类:
public class DynamicProxyTest {
@Testpublic void test(){
Rent rent =new Host();
DynamicProxy proxy = new DynamicProxy(rent);
Rent proxy1 =(Rent) proxy.getProxy(); //获得代理对象 proxy1.rent();
}
}
3.总结:
动态代理和静态代理最大区别就是可以在程序中动态的生成代理对象,使用到了Invocation接口(重写invoke方法),和Proxy(创建代理对象)。
