当前位置: 首页 > news >正文

设计模式-代理模式 - 教程

代理模式(Proxy Pattern)是一种结构型设计模式,它的核心思想是通过代理对象来控制对目标对象的访问。代理对象充当目标对象的代表,客户端实际访问的是代理对象,而不是直接访问目标对象。这种模式在软件开发中有着广泛的应用,特别是在需要对对象访问进行控制、增强或保护的场景。

1. 代理模式的结构

代理模式通常涉及以下三个角色:

  • 抽象主题(Subject):定义了目标对象和代理对象的共同接口,这样在任何使用目标对象的地方都可以使用代理对象。它可以是一个接口或抽象类。例如,在一个图形绘制系统中,可能定义一个 Shape 接口作为抽象主题,包含 draw 方法。
public interface Shape {
void draw();
}
  • 目标对象(RealSubject):实现了抽象主题接口,是实际执行操作的对象。比如,具体的 Circle 类实现了 Shape 接口,是目标对象。
public class Circle implements Shape {
@Override
public void draw() {
System.out.println("Drawing a circle");
}
}
  • 代理对象(Proxy):同样实现了抽象主题接口,内部持有一个目标对象的引用。代理对象在客户端调用时,可以在调用目标对象的方法前后添加额外的逻辑,如访问控制、日志记录等。例如,CircleProxy 类就是代理对象。
public class CircleProxy implements Shape {
private Circle circle;
public CircleProxy() {
this.circle = new Circle();
}
@Override
public void draw() {
System.out.println("Before drawing a circle");
circle.draw();
System.out.println("After drawing a circle");
}
}

2. 代理模式的工作原理

客户端通过代理对象来访问目标对象。当客户端调用代理对象的方法时,代理对象可以在调用目标对象的方法之前或之后执行一些额外的操作,然后再将调用转发给目标对象。例如,在上述图形绘制系统中,客户端代码如下:

public class Client {
public static void main(String[] args) {
Shape circleProxy = new CircleProxy();
circleProxy.draw();
}
}

在这个例子中,客户端创建了 CircleProxy 代理对象并调用其 draw 方法。CircleProxy 在调用 Circledraw 方法前后分别输出了一些信息,实现了对目标对象访问的增强。

3. 代理模式的类型

  • 静态代理:代理类在编译时就已经确定,是手动编写的。如上述 CircleProxy 类就是静态代理的例子,它明确地实现了 Shape 接口,并在内部持有 Circle 对象的引用。静态代理的优点是实现简单,容易理解;缺点是如果目标对象的接口方法很多,代理类的代码会变得冗长,并且当目标对象的接口发生变化时,代理类也需要相应地修改。
  • 动态代理:代理类是在运行时动态生成的。Java提供了两种动态代理方式:JDK动态代理和CGLIB动态代理。
    • JDK动态代理:利用Java反射机制在运行时创建代理类。它要求目标对象必须实现一个接口,通过 Proxy 类和 InvocationHandler 接口来创建代理对象。例如:
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
public class JDKProxyExample {
public static void main(String[] args) {
Circle target = new Circle();
InvocationHandler handler = new InvocationHandler() {
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("Before method invocation");
Object result = method.invoke(target, args);
System.out.println("After method invocation");
return result;
}
};
Shape proxy = (Shape) Proxy.newProxyInstance(
target.getClass().getClassLoader(),
target.getClass().getInterfaces(),
handler);
proxy.draw();
}
}

上述JDk动态代理代码也可分开始
1.先创建动态代理类

public class JDKDynamicProxy implements InvocationHandler {
private Object target;
public JDKDynamicProxy(Object target) {
this.target = target;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("before invoke method");
Object result = method.invoke(target, args);
System.out.println("after invoke method");
return result;
}
}

2.创建工厂类

public class JDKProxyFactory {
public static Object getProxy(Object target) {
return Proxy.newProxyInstance(target.getClass().getClassLoader(),
target.getClass().getInterfaces(),
new JDKDynamicProxy(target)
);
}
}

3.测试

public class JDKProxyTest {
public static void main(String[] args) {
Shape proxy = (Shape)JDKProxyFactory.getProxy(new Circle());
proxy.draw();
}
}
  • CGLIB动态代理:通过字节码生成技术,在运行时为目标类创建一个子类作为代理类。它不需要目标对象实现接口,而是通过继承目标类来创建代理。CGLIB动态代理性能较高,适用于没有实现接口的类。例如:
import net.sf.cglib.proxy.Enhancer;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;
import java.lang.reflect.Method;
public class CGLIBProxyExample {
public static void main(String[] args) {
Enhancer enhancer = new Enhancer();
enhancer.setSuperclass(Circle.class);
enhancer.setCallback(new MethodInterceptor() {
@Override
public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {
System.out.println("Before method invocation");
Object result = proxy.invokeSuper(obj, args);
System.out.println("After method invocation");
return result;
}
});
Circle proxy = (Circle) enhancer.create();
proxy.draw();
}
}

4. 代理模式的适用场景

  • 远程代理:当需要访问远程对象时,使用代理对象来代表远程对象进行访问。例如,在分布式系统中,客户端通过代理对象与远程服务器上的对象进行通信,代理对象负责处理网络连接、序列化/反序列化等细节。
  • 虚拟代理:对于一些创建开销较大的对象,使用代理对象来延迟对象的创建。比如,在一个图像查看器中,当打开一个包含大量高清图片的文件夹时,开始只显示图片的缩略图(代理对象),只有当用户点击查看某张图片时,才真正加载高清图片(目标对象)。
  • 保护代理:用于控制对目标对象的访问权限。例如,在一个多用户系统中,不同用户对某些资源的访问权限不同,代理对象可以在调用目标对象的方法前,检查当前用户的权限,决定是否允许访问。
  • 缓存代理:在代理对象中缓存目标对象的操作结果,以提高性能。比如,对于一些频繁调用且结果不经常变化的方法,代理对象可以缓存方法的返回值,下次相同调用时直接返回缓存结果,而不需要再次调用目标对象。

代理模式通过引入代理对象,有效地将客户端与目标对象分离,增强了系统的灵活性和可维护性,同时提供了对目标对象访问的控制和扩展能力。

比较项JDK动态代理CGLIB动态代理
实现原理利用Java反射机制,在运行时创建实现了目标接口的代理类,通过InvocationHandler回调机制处理方法调用通过ASM字节码生成库,在运行时创建目标类的子类作为代理类,重写目标类方法并借助MethodProxy调用目标方法
代理目标要求目标对象必须实现至少一个接口目标对象可以是普通类,无需实现接口
性能表现代理对象创建速度快,但方法调用通过反射,存在一定性能开销代理对象创建速度慢,因字节码生成较复杂;方法调用直接,性能相对较高
应用场景适用于目标对象已实现接口,且对代理对象创建速度要求较高的场景,如RMI等框架适用于目标对象未实现接口,或对代理对象方法调用性能要求较高的场景,如Spring AOP处理无接口目标对象
代码实现主要依赖Proxy类和InvocationHandler接口,需实现InvocationHandler并重写invoke方法,通过Proxy.newProxyInstance创建代理对象依赖CGLIB库的Enhancer类和MethodInterceptor接口,实现MethodInterceptor并重写intercept方法,借助Enhancer设置目标类、回调函数来创建代理对象
代理类与目标对象关系代理类实现与目标对象相同的接口,持有目标对象引用代理类继承目标类,通过继承获取目标对象的方法
对类成员的代理支持仅能代理接口中定义的方法可代理目标类的所有非final方法,包括private方法(通过反射突破访问限制)
对构造函数的处理不涉及目标类构造函数,通过接口调用目标对象方法可能会影响目标类构造函数调用,因为代理类是目标类的子类,创建代理对象时可能触发目标类构造函数
http://www.jsqmd.com/news/298696/

相关文章:

  • 2025年度AMU260五轴加工中心权威企业排行,帘幕式涂覆机/精密医疗器械加工中心/精密雾化涂覆机AMU260五轴加工中心公司有哪些
  • WebGL 笔记
  • 2025年电缆网套回购大赏,这些厂商值得你信赖!环形吊带/钢锭吊具/成套索具/复合钢丝绳,电缆网套生产厂家哪家靠谱
  • 使用torch.compile与梯度累积加速模型训练
  • 王同學文章轉載公告
  • 做社区垃圾分类指导工具,输入垃圾名称,自动识别所属分类(可回收/厨余/有害/其他),标注时间,投放点,附详细分类说明。
  • DBShadow.net之化繁为简
  • 无锡、杭州升降平台厂商价格比较,哪个更合适?
  • 聊聊同质透心pvc地板精品定制,新凯琳厂家优势在哪?
  • 南京整装装修专业公司哪家好,红牛装饰实力揭秘
  • 计算机毕业设计springboot房屋租赁管理系统 基于SpringBoot的在线房屋出租与求租撮合平台 SpringBoot+Vue智慧住房租赁综合服务平台
  • 计算机毕业设计springboot房屋租赁管理系统 基于SpringBoot的在线房源租售一体化运营平台 SpringBoot+Thymeleaf智慧住房租赁合约管理系统
  • 工程防火材料选型指南:深度解读消防验收标准下的廊坊大浩防火涂料方案,防火涂料/电缆防火涂料,防火涂料供应商排行榜单
  • 2026火锅测评:哪些网红品牌值得一试?重庆火锅/美食/社区火锅/牛肉火锅/老火锅/附近火锅/火锅,火锅品牌推荐排行
  • 如何使用 GitHub Actions + image-syncer 实现 Docker Hub 到 Azure ACR 的自动化镜像同步
  • 计算机毕业设计springboot防诈知识在线学习系统 基于SpringBoot的反诈骗科普互动学习平台 SpringBoot+Vue智慧防诈在线教育系统
  • Java毕设项目:基于springboot的私厨服务平台的设计与实现(源码+文档,讲解、调试运行,定制等)
  • 计算机毕业设计springboot房屋租赁系统 基于SpringBoot的在线房屋出租与求租撮合平台 SpringBoot+Vue智慧住房租赁综合服务平台
  • 计算机毕业设计springboot房车旅途 基于SpringBoot的房车租赁与售卖一体化平台 SpringBoot+Vue智慧房车出行服务系统
  • 计算机毕业设计springboot房源出租信息系统 基于SpringBoot的在线房屋租售一体化平台 SpringBoot+Vue智慧房源租赁撮合系统
  • Java计算机毕设之基于java+springboot的花店鲜花销售管理系统基于springboot的鲜花销售管理系统的设计与实现(完整前后端代码+说明文档+LW,调试定制等)
  • Java计算机毕设之基于Springboot的社区老年人健康管理系统基于springboot的社区独居老人健康管理系统(完整前后端代码+说明文档+LW,调试定制等)
  • 2026年靠谱的微压富氧舱解决方案大揭秘,原力氧FVIP值得关注
  • 【毕业设计】基于springboot的私厨服务平台的设计与实现(源码+文档+远程调试,全bao定制等)
  • 【课程设计/毕业设计】基于springboot+vue的社区独居老人健康管理系统基于springboot的社区空巢老人健康管理系统 社区独居老人健康管理系统【附源码、数据库、万字文档】
  • 肯能机械口碑如何,江西包装机厂家排名有它吗?
  • 【毕业设计】基于springboot的社区独居老人健康管理系统(源码+文档+远程调试,全bao定制等)
  • 说说升降平台供应企业哪家专业,无锡固佳工业设备上榜
  • 润滑油泵选型怎么选,专业支招让你不再迷茫
  • 用一套开源AI视觉系统,提升商场促销活动效果