代理模式 (Proxy Pattern)

embedded/2024/11/28 16:25:20/

文章目录

      • 代理模式 (Proxy Pattern)
      • 原理
      • 分类
      • 优点
      • 缺点
      • 示例代码
        • 静态代理
          • 1. 定义接口
          • 2. 创建真实类
          • 3. 创建代理类
          • 4. 客户端代码
          • 输出结果
        • 动态代理(基于 JDK)
          • 1. 定义接口和真实类
          • 2. 创建动态代理类
          • 3. 客户端代码
          • 输出结果
      • UML 类图
        • 静态代理
        • 动态代理
      • 使用场景
      • 小结

代理模式 (Proxy Pattern)

代理模式是一种 结构型设计模式,它为某个对象提供一个替代或占位符,用来控制对这个对象的访问。通过代理对象,可以在实际对象的前后加入额外的功能(如权限校验、日志记录等)。


原理

  1. 核心思想
    • 使用一个代理类代表实际对象,客户端通过代理类间接访问实际对象。
  2. 适用场景
    • 控制对实际对象的访问(如权限验证)。
    • 增强功能(如日志记录、延迟加载)。
    • 远程代理、虚拟代理等场景。
  3. 参与角色
    • Subject(抽象主题类):定义真实对象和代理对象的公共接口。
    • RealSubject(真实主题类):实现抽象主题,表示被代理的真实对象。
    • Proxy(代理类):实现抽象主题,内部持有真实主题的引用,用来控制访问和增强功能。

分类

  1. 静态代理:代理类在编译时生成,开发者需要手动编写代理类。
  2. 动态代理:代理类在运行时动态生成,无需手动编写。
    • 基于 JDK 的动态代理(必须实现接口)。
    • 基于 CGLIB 的动态代理(无需接口)。

优点

  1. 控制访问:可以对访问真实对象进行约束。
  2. 功能扩展:通过代理类,在真实对象前后加入增强功能。

缺点

  1. 增加复杂性:引入代理类后,代码复杂度增加。
  2. 性能开销:动态代理会带来一定的性能消耗。

示例代码

静态代理

场景:一个 Payment 接口,有具体的支付实现。通过代理类对支付操作进行日志记录。


1. 定义接口
// 抽象主题
public interface Payment {void pay(int amount);
}

2. 创建真实类
// 真实主题类
public class RealPayment implements Payment {@Overridepublic void pay(int amount) {System.out.println("Processing payment of $" + amount);}
}

3. 创建代理类
// 代理类
public class PaymentProxy implements Payment {private RealPayment realPayment;public PaymentProxy(RealPayment realPayment) {this.realPayment = realPayment;}@Overridepublic void pay(int amount) {System.out.println("Logging: Initiating payment...");realPayment.pay(amount); // 调用真实对象的方法System.out.println("Logging: Payment completed.");}
}

4. 客户端代码
public class StaticProxyExample {public static void main(String[] args) {RealPayment realPayment = new RealPayment(); // 创建真实对象Payment proxy = new PaymentProxy(realPayment); // 创建代理对象proxy.pay(100); // 使用代理对象}
}

输出结果
Logging: Initiating payment...
Processing payment of $100
Logging: Payment completed.

动态代理(基于 JDK)

场景:通过动态代理实现相同的功能,无需手动编写代理类。


1. 定义接口和真实类
// 抽象主题
public interface Payment {void pay(int amount);
}// 真实主题类
public class RealPayment implements Payment {@Overridepublic void pay(int amount) {System.out.println("Processing payment of $" + amount);}
}

2. 创建动态代理类
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;// 动态代理类
public class DynamicProxyHandler implements InvocationHandler {private Object realObject;public DynamicProxyHandler(Object realObject) {this.realObject = realObject;}@Overridepublic Object invoke(Object proxy, Method method, Object[] args) throws Throwable {System.out.println("Logging: Before method call...");Object result = method.invoke(realObject, args); // 调用真实对象的方法System.out.println("Logging: After method call...");return result;}// 获取代理实例public static Object getProxyInstance(Object realObject) {return Proxy.newProxyInstance(realObject.getClass().getClassLoader(),realObject.getClass().getInterfaces(),new DynamicProxyHandler(realObject));}
}

3. 客户端代码
public class DynamicProxyExample {public static void main(String[] args) {RealPayment realPayment = new RealPayment(); // 创建真实对象Payment proxy = (Payment) DynamicProxyHandler.getProxyInstance(realPayment); // 获取代理实例proxy.pay(200); // 使用代理对象}
}

输出结果
Logging: Before method call...
Processing payment of $200
Logging: After method call...

UML 类图

静态代理
    +------------+       +-------------+|  Payment   |<------+ RealPayment |+------------+       +-------------+^                     ^|                     |+-------------------------------+|         PaymentProxy          |+-------------------------------+
动态代理
    +------------+       +-------------+|  Payment   |<------+ RealPayment |+------------+       +-------------+^|+-------------+| Proxy       |+-------------+

使用场景

  1. 远程代理:为远程对象提供本地代理(如 RMI)。
  2. 虚拟代理:延迟加载资源,按需加载实际对象。
  3. 保护代理:对访问进行权限控制。
  4. 日志、性能监控:在方法调用前后增加日志或监控逻辑。

小结

  • 静态代理:需要手动编写代理类,适用于代理逻辑较少且稳定的场景。
  • 动态代理:无需手动编写代理类,灵活性强,适用于接口较多或逻辑频繁变化的场景。
  • 代理模式解耦了客户端与实际对象,增强了系统的灵活性和扩展性。

http://www.ppmy.cn/embedded/141219.html

相关文章

Qt中的套件(如MSVC2019)提示no complier set in kit

起因 是我想在qt创建自定义控件新建项目的时候发现有黄色警告&#xff1a;提示no complier set in kit 但是其实我早发现了但是我选择忽视然后选择了minGW编译器。。。。但是现在我不得不解决呜呜呜呜&#xff08;小声&#xff09; 提示原因是因为没有编译器&#xff0c;所以…

【Python爬虫五十个小案例】爬取豆瓣电影Top250

博客主页&#xff1a;小馒头学python 本文专栏: Python爬虫五十个小案例 专栏简介&#xff1a;分享五十个Python爬虫小案例 &#x1fab2;前言 在这篇博客中&#xff0c;我们将学习如何使用Python爬取豆瓣电影Top250的数据。我们将使用requests库来发送HTTP请求&#xff0c;…

HarmonyOS开发:DevEco Studio的Beta3(5.0.5.200)新增和增强特性

新增特性 DevEco Studio支持开发API 13工程。DevEco Profiler Frame模板新增Lost Frames和Hitch Time泳道&#xff0c;用于识别和优化卡顿和丢帧现象。具体请参考Frame分析。hvigor-config.json5中properties下新增ohos.arkCompile.noEmitJs字段&#xff0c;用于指定ArkTS编译…

基于 Nginx Ingress Controller 的四层(TCP)转发配置

基于 Nginx Ingress Controller 的四层&#xff08;TCP&#xff09;转发配置 1. 简介 本指南将展示如何通过配置 ConfigMap 来实现 Nginx Ingress Controller 的四层转发&#xff08;TCP&#xff09;&#xff0c;并通过配置测试应用程序验证配置的有效性。本文中使用的 Kuber…

ChatGPT的应用场景:开启无限可能的大门

ChatGPT的应用场景:开启无限可能的大门 随着人工智能技术的快速发展,自然语言处理领域迎来了前所未有的突破。其中,ChatGPT作为一款基于Transformer架构的语言模型,凭借其强大的语言理解和生成能力,在多个行业和场景中展现出了广泛的应用潜力。以下是ChatGPT八个最具代表…

人工智能在医疗保健领域的潜在应用

人工智能在医疗保健领域的潜在应用 一、影像识别与辅助诊断 医学影像解读 医学影像解读一直是医生的重要工作之一&#xff0c;然而由于医学影像学习曲线陡峭、误诊率高等问题&#xff0c;这一领域迫切需要人工智能技术的介入。利用深度学习算法&#xff0c;人工智能可以对医学影…

汽车免拆诊断案例 | 2017款捷豹F-PACE车发动机偶尔怠速不稳

故障现象  一辆2017款捷豹F-PACE车&#xff0c;搭载2.0 L GTDi发动机&#xff0c;累计行驶里程约为16万km。车主反映&#xff0c;车辆组合仪表上发动机故障灯点亮&#xff08;图1&#xff09;&#xff0c;且发动机偶尔怠速不稳。 图1 发动机故障灯点亮 故障诊断 接车后试车…

Brain.js 用于浏览器的 GPU 加速神经网络

Brain.js 是一个强大的 JavaScript 库&#xff0c;它允许开发者在浏览器和 Node.js 环境中构建和训练神经网络 。这个库的目的是简化机器学习模型的集成过程&#xff0c;使得即使是没有深厚机器学习背景的开发者也能快速上手 。 概述 Brain.js 提供了易于使用的 API&#xff…