说起代理模式,我算是对他三进三出了,文章至少写的有两篇了,但是我再去看的时候,总感觉不太容易理解,今天来一个我自己的真实案例,通过暑假实习找房子的经历来进行讲解代理模式。
静态代理
代理模式的话,大致可以分为两种,其一是静态代理,其二是动态代理,静态代理的话,相对简单点。先来一个我暑假的租房场景~
暑假的时候,我一个人来到了杭州,找了一个实习,然后我问HR,附近哪个小区的房子比较不错(第一件事租房),然后他说“福鼎家园”,于时我就来到了福鼎,旁边有一个小房间,好像是暂住证登记的地方,我就问他,这边有房子出租吗?然后他就给我打了个电话,叫过来一个阿姨,然后带我看房子,这些房子是哪来的呢(第二件事房东把房子注册到中介),原来都是房东的房子,只是中介带我看罢了,然后看了好多套房子(第三件事跟着中介看房子),终于看到了一个小房间,我很满意,然后就签了(最后我成功的租到了房子)
第一件事,从上面的简单描述可以看出,这一切的一切,都源于你要干一件事,那就是租房子,也就是说,你得有需求。
// 首先要有一个需求,也就是要租房子,这个需求不用实现,让房东和代理去实现
public interface Rent {
public void rent();
}
第二件事,有了租房的需求,是不是得有房东出租房子呀,要不然也没得租呀。
// 房东实现Rent接口,做出租房子这件事
public class Host implements Rent {
public void rent() {
System.out.println("房东出租房子");
}
}
第三件事,有了房东要出租房子了,代理是不是可以帮助房东了,代理的出现,主要是可以完成房东的一些杂事,例如看房子和“忽悠”,而房东只需出租房子就行了(房东的事情比较单一了)。
public class Proxy implements Rent{
private Host host;
public void setHost(Host host) {
this.host = host;
}
public void rent() {
//这里是代理帮助房东出租房子
host.rent();
}
public void watch() {
System.out.println("看房子,一家一家又一家,我中介从不怕累。。。");
}
}
最后成功套娃
public class Client {
public static void main(String[] args) {
Host host = new Host();
Proxy proxy = new Proxy();
proxy.setHost(host);
proxy.rent();
}
}
经过这一波一换五,终于摧毁了敌方的水晶,稳赚不赔,此时房东达到了目的,成功出租房子,中介(代理)达到了目的,成功拿到了中介费,我也达到了目的,成功被中介套路(找到了心仪的房子)。
聪明的小朋友一定会发现一个问题,这里的房东只有一个,也就是Host,而中介也是一个Proxy。聪明的中介可能只做一个房东的代理吗,我觉得不会,汽车跑高速还有备胎呢。那问题来了,一个中介怎么才能代理多个房东呢(脚踏多只船),这个有点难度呀,仔细想想也不难,我一个代理去组合多个房东不就可以了吗(生活经验丰富的你说的没错,但是程序不好写呀。。。)这样一来,也就是每当有新的房东要出租房子的时候,都可以注册到中介这,有那么一丝丝的动态的感觉了,也就是接下来要讲的动态代理。
动态代理
动态代理的牛逼之处,就是代理这个角色,这里通过JDK提供的动态代理来实现,这种方式是基于接口的,还有一种是CGlib,基于类的。
第一件事同样的出租房子这件事不变
// 出租房子的需求
public interface Rent {
public void rent();
}
第二件事有房东出租房子,也不变
public class Host implements Rent {
public void rent() {
System.out.println("房东出租房子");
}
}
第三件事生成代理类,这个就是动态代理的核心了,通过JDK提供的Proxy类和InvocationHandler接口来实现。
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
//该类会自动生成代理类
public class ProxyInvocationHandler implements InvocationHandler{
//被代理的接口
private Rent rent;
public void setRent(Rent rent) {
this.rent = rent;
}
//生成代理类
public Object getProxy() {
return Proxy.newProxyInstance(this.getClass().getClassLoader(),rent.getClass().getInterfaces(),this);
}
//处理代理程序,并返回结果
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
//动态代理的本质,用反射机制
seeHost();//被扩展的功能可以直接加到这
Object result = method.invoke(rent,args);
return result;
}
//在这里可以扩展功能
public void seeHost() {
System.out.println("代理带看房子");
}
}
最后仍然是成功租到房子
import com.sun.org.apache.regexp.internal.RE;
public class Client {
public static void main(String[] args) {
//这是真实角色,也就是我们的房东
Host host = new Host();
//创建代理调用处理角色
ProxyInvocationHandler proxyInvocationHandler = new ProxyInvocationHandler();
//通过调用程序处理角色来处理我们要调用的接口对象
proxyInvocationHandler.setRent(host);
//创建代理对象
Rent proxy = (Rent) proxyInvocationHandler.getProxy();
proxy.rent();
}
总结
不管是动态代理还是静态代理,其本质都是让“房东”的业务变得单一,只是负责出租房子,一些繁琐的事情例如,看房子,“套娃”,跑腿等,都交给中介做了。这样做的好处是,实现了业务分工,当业务扩展时,方便集中管理