1. 代理模式的定义

代理模式(Proxy Pattern)是指通过代理对象控制对目标对象的访问,并在不改变目标对象的情况下添加额外的功能或控制访问。代理对象和目标对象实现相同的接口,使得客户端可以通过代理对象间接地访问目标对象。

代理模式属于结构型设计模式,它在系统中引入了一个代理对象,该对象代替了客户端直接访问目标对象,从而可以在目标对象的基础上增加一些额外的功能或控制访问。

2. 代理模式的原理

代理模式的核心思想是引入一个代理对象来控制对目标对象的访问。代理对象和目标对象实现相同的接口,使得客户端可以通过代理对象间接地访问目标对象。代理对象负责处理客户端的请求,并在必要时将请求转发给目标对象。在这个过程中,代理对象可以添加额外的逻辑,如权限检查、缓存、日志记录等。

代理模式的主要角色有

  • 抽象主题(Subject)定义了代理对象和目标对象的共同接口,在Java中通常是一个接口或抽象类。
  • 目标对象(RealSubject)定义了代理对象所代表的真实对象,是业务逻辑的具体执行者。
  • 代理对象(Proxy)持有对目标对象的引用,并实现了与目标对象相同的接口,在方法调用前后进行额外操作。

代理模式的工作流程如下

  • 客户端向代理对象发送请求。
  • 代理对象收到请求后,可以在请求被转发给目标对象之前或之后执行一些额外的逻辑。
  • 代理对象将请求转发给目标对象。
  • 目标对象执行具体的业务逻辑并返回结果。
  • 代理对象可以在目标对象返回结果之前或之后执行一些额外的操作。
  • 代理对象将结果返回给客户端。

通过引入代理对象,代理模式可以控制对目标对象的访问,并在不改变目标对象的情况下添加额外的功能或控制访问。

3. 代理模式的实现方式

在Java中,代理模式主要有两种实现方式静态代理和动态代理。

3.1 静态代理

静态代理是指在编译时就已经确定了代理对象和目标对象的关系,代理类是通过手动编写代码来实现的。在静态代理中,代理类和目标类都实现相同的接口,代理类持有目标对象,并在方法调用前后进行额外的操作。

Java代理模式之静态代理与动态代理的区别及优缺点静态代理的工作原理如下

  • 定义一个接口(或抽象类)作为目标接口,目标对象实现这个接口。
  • 创建一个代理类,实现目标接口,并持有目标对象的引用。
  • 在代理类中重写目标接口的方法,在方法调用前后执行需要的额外操作。
  • 客户端使用代理对象来访问目标对象。

静态代理的特点

  • 需要手动编写代理类,工作量较大。
  • 目标对象必须实现接口。
  • 代理类和目标类的关系在编译时就确定了,无法动态改变。

静态代理的应用场景

  • 安全控制代理类可以在调用目标方法前进行权限检查等安全控制。
  • 远程调用代理类可以封装网络通信相关的细节,使得调用远程方法就像调用本地方法一样简单。
  • 性能监控代理类可以收集方法的执行时间、调用次数等信息,用于性能监控和统计分析。

下面是一个简单的静态代理的示例代码

ImageRealImageImageProxyProxyPatternDemo
ImageProxydisplay()display()RealImagedisplay()display()display()

静态代理的缺点是需要手动编写代理类,工作量较大。如果接口中的方法较多或频繁变动,就需要频繁修改代理类的代码,增加了维护的难度。此外,静态代理的代理类和目标类之间存在紧耦合关系,一旦目标类发生变化,代理类也需要相应修改。

为了解决静态代理的缺点,Java还提供了动态代理机制。

3.2 动态代理

java.lang.reflect.Proxyjava.lang.reflect.InvocationHandler
InvocationHandler

动态代理的工作原理如下

InvocationHandlerProxynewProxyInstance()InvocationHandler

动态代理的特点

  • 不需要手动编写代理类,代理对象在运行时动态生成。
  • 目标对象可以不实现接口,只需定义目标对象的共同接口。
  • 代理对象和目标对象的关系在运行时确定,可以动态改变。

动态代理的应用场景

  • AOP(面向切面编程)动态代理可以在目标方法执行前后执行额外的操作,如权限检查、事务管理等。它是实现AOP的一种常见方式。
  • 延迟加载动态代理可以在目标方法被调用时才进行加载和初始化,实现延迟加载的效果。
  • 日志记录动态代理可以在目标方法执行前后记录日志信息。

下面是一个简单的动态代理的示例代码

ImageRealImageImageInvocationHandlerInvocationHandlerProxyPatternDemo
RealImageImageInvocationHandlerProxynewProxyInstance()display()
InvocationHandlerinvoke()invoke()
阅读剩余 0%
本站所有文章资讯、展示的图片素材等内容均为注册用户上传(部分报媒/平媒内容转载自网络合作媒体),仅供学习参考。 用户通过本站上传、发布的任何内容的知识产权归属用户或原始著作权人所有。如有侵犯您的版权,请联系我们反馈本站将在三个工作日内改正。