这里使用真实案例
抽象角色:租房
真实角色:房东
代理角色:中介
用户:和中介打交道而不和房东直接打交道
1.创建抽象角色
public interface Rent {
//租房
void rentHouse();
}
2.创建真实角色
//房东
public class Host implements Rent{
public void rentHouse() {
System.out.println("房东要租房子");
}
}
3.创建代理角色
//中介
public class Zhongjie implements Rent{
//中介要代理房东这个角色
private Host host;
public Zhongjie(Host host) {
this.host = host;
}
//也重写了接口的方法,但不是中介租房,而是房东租房子
//并且可以干一些其他事情,比如看房子,签合同
public void rentHouse() {
seeHouse();
host.rentHouse();
qianhetong();
}
public void qianhetong(){
System.out.println("签合同");
}
public void seeHouse(){
System.out.println("看房子");
}
}
4.用户测试
public class Test {
public static void main(String[] args) {
//实例化一个房东对象
Host host = new Host();
//中介代理房东,所以将房东对象传给中介
Zhongjie zhongjie = new Zhongjie(host);
//中介调用租房子方法
zhongjie.rentHouse();
}
}
5.结果
分析:在这个过程中,你直接接触的就是中介,就如同现实生活中的样子,你看不到房东,但是你依旧租到了房东的房子通过代理,这就是所谓的代理模式,程序源自于生活,所以学编程的人,一般能够更加抽象的看待生活中发生的事情。
静态代理的好处:
缺点:
我们想要静态代理的好处,又不想要静态代理的缺点,所以 , 就有了动态代理 !
动态代理和静态代理的区别
动态代理分为两种
这里将基于接口的动态代理
1.创建抽象角色
public interface Renting {
//租房
void rentingHouse();
}
2.创建真实对象
//房东
public class HouseHost implements Renting{
public void rentingHouse() {
System.out.println("房东出租房子!");
}
}
3.创建代理处理类
public class ProxyInvocationHandler implements InvocationHandler {
//代理的抽象角色
//动态代理代理的不再是一个角色,而是一类角色,所以传的是接口
private Renting renting;
public void setRenting(Renting renting) {
this.renting = renting;
}
//生成代理类
//newProxyInstance(arg1,arg2,arg3)参数
//arg1:实现InvocationHandler 接口的类加载器
//arg2:抽象角色也就是接口
//arg3:实现InvocationHandler 接口的类的实例
public Object getProxy(){
return Proxy.newProxyInstance(ProxyInvocationHandler.class.getClassLoader(),
renting.getClass().getInterfaces(),
this);
}
// 处理代理实例上的方法调用并返回结果
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
//核心:反射实现的
Object result = method.invoke(renting, args);
return result;
}
}
将ProxyInvocationHandler 类中的接口换成Object类型,就可以处理不同业务,代码如下:
public class ProxyInvocationHandler implements InvocationHandler {
private Object object;
public void setRenting(Object object) {
this.object = object;
}
public Object getProxy(){
return Proxy.newProxyInstance(ProxyInvocationHandler.class.getClassLoader(),
object.getClass().getInterfaces(),
this);
}
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
Object result = method.invoke(object, args);
return result;
}
}
4.测试
public class Test {
public static void main(String[] args) {
//创建抽象角色的实例
Renting host = new HouseHost();
ProxyInvocationHandler proxyInvocationHandler = new ProxyInvocationHandler();
//代理一类角色
proxyInvocationHandler.setRenting(host);
//生成代理对象
Renting proxy = (Renting) proxyInvocationHandler.getProxy();
//调用方法
proxy.rentingHouse();
}
}
第3,4步也可这样写
3.创建代理处理类
public class ProxyInvocationHandler implements InvocationHandler {
private Renting renting;
public void setRenting(Renting renting) {
this.renting = renting;
}
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
Object result = method.invoke(renting, args);
return result;
}
}
4.测试
public class Test {
public static void main(String[] args) {
Renting host = new HouseHost();
ProxyInvocationHandler proxyInvocationHandler = new ProxyInvocationHandler();
//代理一类角色
proxyInvocationHandler.setRenting(host);
//生成代理对象
Renting proxy = (Renting) Proxy.newProxyInstance(proxyInvocationHandler.getClass().getClassLoader()
, host.getClass().getInterfaces()
, proxyInvocationHandler);
proxy.rentingHouse();
}
}
结果相同,写法不同
动态代理的好处