设计模式之代理模式
Posted ProChick
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了设计模式之代理模式相关的知识,希望对你有一定的参考价值。
1.简要概述
- 代理模式就是通过代理对象来控制对真实对象的访问,也就是详细的控制访问某个对象的方法,从而将一些统一的流程代码放到代理类中处理。
- 代理模式中,被代理的对象可以是远程对象、创建开销大的对象、需要安全控制的对象。
- 代理模式是面向切面编程的核心实现思想。
2.模式分类
-
静态代理
在静态代理中,需要定义一个公共接口,代理对象和被代理对象都要实现这个公共接口中的方法。
// 教师接口 public interface CommonTeacher{ void teach(); } // 真实教师角色 public class RealTeacher implements CommonTeacher{ @Override public void teach(){ System.out.println("开始上课"); } } // 代理教师角色 public class ProxyTeacher implements CommonTeacher{ private CommonTeacher realTeacher; public ProxyTeacher(CommonTeacher realTeacher){ this.realTeacher = realTeacher; } @Override public void teach(){ System.out.println("通知某个教师"); realTeacher.teach(); } } // 测试客户端 public class Client{ public static void main(String[] args) { ProxyTeacher proxy = new ProxyTeacher(new RealTeacher()); proxy.teach(); } }
👉优点:在不修改目标对象功能的前提下,能够通过代理对象实现对目标对象的扩展。
👉缺点:由于代理对象和目标对象都要实现统一的接口,一旦接口中增加新的功能方法,那么二者都需要进行更改实现。
-
JDK动态代理
在JDK动态代理中,需要定义一个接口,被代理对象要实现这个接口中的方法。但代理对象不需要实现接口,而是利用JDK中提供的API,动态的在内存中构建代理对象。
// 教师接口 public interface CommonTeacher{ void teach(); } // 真实教师角色 public class RealTeacher implements CommonTeacher{ @Override public void teach(){ System.out.println("开始上课"); } } // 代理教师角色 public class ProxyTeacher implements InvocationHandler{ private CommonTeacher realTeacher; public ProxyTeacher(CommonTeacher realTeacher){ this.realTeacher = realTeacher; } @Override public Object invoke(Object proxy, Method method, Object[] args){ if(method.getName().equals("teach")) { System.out.println("通知某个教师"); method.invoke(realTeacher, args); } return null; } public Object getProxy(){ return Proxy.newProxyInstance( ClassLoader.getSystemClassLoader(), new Class[] {CommonTeacher.class}, realTeacher); } } // 测试客户端 public class Client{ public static void main(String[] args) { ProxyTeacher proxy = new ProxyTeacher(new RealTeacher()); CommonTeacher teacher = (CommonTeacher) proxy.getProxy(); teacher.teach(); } }
👉优点:它是Java原生支持的API,不需要任何其它第三方依赖
👉缺点:它只能基于接口进行实现
-
Cglib代理
在Cglib动态代理中,不需要定义接口,需要定义一个类去实现Cglib包中的MethodInterceptor类,然后在重写的intercept方法中完成被代理对象的调用,最后再通过Enhance工具类生成被代理对象的一个子类,让这个子类充当代理对象。Cglib是一个高性能的代码生成包,底层是通过使用字节码处理框架ASM来转换并生成新的类。
// 真实教师角色 public class RealTeacher{ public void teach(){ System.out.println("开始上课"); } } // 代理教师角色 public class ProxyTeacher implements MethodInterceptor{ private RealTeacher realTeacher; public ProxyTeacher(RealTeacher realTeacher){ this.realTeacher = realTeacher; } @Override public Object intercept( Object arg0, Method arg1, Object[] arg2, MethodProxy arg3){ System.out.println("通知某个教师"); Object result = arg3.invokeSuper(arg0, arg2); return result; } public Object getProxy(){ Enhancer enhancer = new Enhancer(); enhancer.setSuperclass(RealTeacher.class); enhancer.setCallback(realTeacher); return (RealTeacher) enhancer.create(); } } // 测试客户端 public class Client{ public static void main(String[] args) { ProxyTeacher proxy = new ProxyTeacher(new RealTeacher()); ProxyTeacher teacher = (ProxyTeacher) proxy.getProxy(); teacher.teach(); } }
👉优点:它与代理的目标对象没有使用限制,无需定义和实现任何接口
👉缺点:无法处理被final修饰的方法,因为在创建子类对象的时候无法继承
3.模式结构
👉通常由一个抽象角色(
负责定义真实角色和代理角色的一些公共方法
),一个代理角色(负责通过真实角色的业务逻辑方法来实现抽象方法,并附加一些别的操作
),一个真实角色(负责实现抽象角色,定义真实角色所要实现的业务逻辑供代理角色调用
),一个客户类(负责调用代理对象,完成对真实角色的访问
)共同组成。
4.实现代码
举例 💡 :假设我们现在要租房,而房东希望我们先和中介进行商量已确定价格,然后我们才给房东进行付钱,那么这个处理过程我们就可以使用代理模式处理。
房子(抽象角色)
public interface House {
// 谈价格
void talk();
// 付租金
void pay();
}
房子中介(代理角色)
public class HouseProxy implements House{
private Landlord landlord;
public HouseProxy(Landlord landlord) {
this.landlord = landlord;
}
@Override
public void talk() {
System.out.println("找中介谈价格");
}
@Override
public void pay() {
landlord.pay();
}
}
房东(真实角色)
public class Landlord implements House{
@Override
public void talk() {
System.out.println("");
}
@Override
public void pay() {
System.out.println("给房东付钱");
}
}
客户类
// 测试客户端
public class HouseClient{
public static void main(String[] args) {
House proxy = new HouseProxy(new Landlord());
proxy.talk();
proxy.pay();
}
}
5.优点好处
- 代理对象可以在客户端和目标对象之间起到中介的作用,这样就起到了保护了目标对象的作用。
- 代理对象可以扩展目标对象的功能。
- 代理模式能将客户端与目标对象分离,在一定程度上降低了系统的耦合度。
6.缺点弊端
- 在客户端和目标对象之间增加一个代理对象,会造成请求处理速度变慢。
- 一定程度上增加了系统的复杂度。
7.应用场景
- 当我们想通过代理来控制对远程对象的访问,可以使用远程代理。
- 当我们想利用权限来控制对对象的访问,以此来屏蔽对真实对象的直接访问,可以使用安全代理。
- 当我们需要创建开销很大的对象,先加载一个轻量级的代理对象,以便延迟对真实对象的访问,可以使用虚拟代理。
- 当我们在处理真实对象的时候,希望代理去处理另外一些事情,可以使用智能代理。
8.应用示例
Spring源码中的AOP面向切面编程
以上是关于设计模式之代理模式的主要内容,如果未能解决你的问题,请参考以下文章