什么是代理模式?
类似于中介,我们面对的对象变成了中介,而不是用户个体,例如租房子:
![](https://img.haomeiwen.com/i20466038/ff6ccad78b5ee14e.png)
1、静态代理
角色分析:
- 抽象角色:真实的目的性,一般是接口或者抽象类来解决
- 真实角色:被代理的角色
- 代理角色:代理真实角色,代理真实角色后,一般进行一些附属操作
- 客户:访问代理对象的人,办理真实业务的人
步骤:
1.接口
public interface Rent {
//租房
void rent();
}
2.真实角色
public class Landlord implements Rent{
public void rent() {
System.out.println("房东出租了房子~");
}
}
3.代理角色
public class Proxy implements Rent {
private Landlord landlord;
public Proxy() {
}
public Proxy(Landlord landlord) {
this.landlord = landlord;
}
//额外的操作
public void seeHouse(){
System.out.println("中介带看房~");
}
public void hetong(){
System.out.println("中介签合同~");
}
public void fare(){
System.out.println("中介收租~");
}
public void rent() {
seeHouse();
hetong();
//真实的租房业务
landlord.rent();
fare();
}
}
4.访问
public class Client {
public static void main(String[] args) {
//房东
Landlord landlord = new Landlord();
//中介代理房东
Proxy proxy = new Proxy(landlord);
//租房业务
proxy.rent();
}
}
5、结果
/**
中介带看房~
中介签合同~
房东出租了房子~
中介收租~
/
真实的租房业务还是房东,但是在中介代理后会进行了一些附加的操作。
优点:
- 真实的业务对象更加关注自己的业务,不用在意一些公共的业务
- 公共交给代理,实现了业务分工
- 在不修改目标对象的功能前提下, 能通过代理对象对目标功能扩展
缺点:
- 每一个实际的对象都对应一个代理对象,复杂度增加
- 一旦公共接口增加方法,目标对象与代理对象都要维护
2、动态代理
- 动态代理角色和静态代理是一样的
- 动态代理的代理类是动态生成的,不是直接写好的
- 动态代理分两大类:基于接口的动态代理,基于类的动态代理
- 基于接口: JDK动态代理
- 基于类:cglib
- java字节码实现:javassist
需要理解两个类:Porxy 和 InvocationHandler
Porxy:提供了创建动态代理类和实例的静态方法,它也是由这些方法创建的所有动态代理类的超类,专门用来创建代理对象。
InvocationHandler:是调用代理实例的程序实现的接口,动态实现,每个代理实例都有一个关联的调用处理程序。 当在代理实例上调用方法时,方法调用将被编码并分派到其调用处理程序的invoke方法。
还是以租房子为例:
1.接口
public interface Rent {
void rent();
}
2.真实对象
public class Landlord implements Rent {
public void rent() {
System.out.println("房东出租了房子~");
}
}
3.真实对象处理类
public class ProxyInvocationHandler implements InvocationHandler {
//被代理的接口 这里可以通配
private Object target;
public void setTarget(Object target) {
this.target = target;
}
//动态的获取代理类 固定写法
public Object getPorxy(){
/**
* 参数
*loader - 类加载器来定义代理类
* interfaces - 代理类实现的接口列表
* h - 调度方法调用的调用处理函数
*/
return Proxy.newProxyInstance(this.getClass().getClassLoader(),target.getClass().getInterfaces(),this);
}
//处理被代理的实例 返回结果
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
seeHouse();
hetong();
//真实的租房业务
// this.log(method.getName());
//处理真实的代理对象业务
Object result = method.invoke(target,args);
fare();
return result;
}
//额外的操作
// public void log(String msg){
// System.out.println("操作了"+msg+"方法");
// }
public void seeHouse(){
System.out.println("中介带看房~");
}
public void hetong(){
System.out.println("中介签合同~");
}
public void fare(){
System.out.println("中介收租~");
}
}
4.测试
public static void main(String[] args) {
//真实对象
Landlord landlord = new Landlord();
ProxyInvocationHandler handler = new ProxyInvocationHandler();
//告诉处理器要代理的真实对象
handler.setTarget(landlord);
//获取代理角色 动态生成的
Rent porxy = (Rent) handler.getPorxy();
//调用真实的业务
porxy.rent();
}
结论:
这里的代理对象是通过处理类动态的获取的,而且通过通配改造之后,该处理类可以代理一类的需要代理的对象,只要是实现了同一个接口的对象都可以动态的获取到代理对象。
优点:
- 基于静态代理的基础上,一个动态代理类代理的是一个接口,一般就是对应的一类业务
- 一个动态代理类可以代理多个类,只要是实现了同一个接口的
网友评论