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

代理模式 (Proxy Pattern)

文章目录

      • 代理模式 (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 {
    @Override
    public 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;
    }

    @Override
    public 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 {
    @Override
    public 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;
    }

    @Override
    public 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.kler.cn/a/412300.html

相关文章:

  • npm install -g@vue/cli报错解决:npm error code ENOENT npm error syscall open
  • RTMP协议
  • 大数据面试SQL题-笔记02【查询、连接、聚合函数】
  • Oracle RAC的DB未随集群自动启动
  • 如何使用GCC手动编译stm32程序
  • 4.6 JMeter HTTP信息头管理器
  • C#基础36-40
  • 【大数据测试 Elasticsearch 的 四大 常见问题及处理方案】
  • 【模糊查询Redis的Key,过滤出其中ZSET类型中包含自定义字符串的元素并删除】
  • 老旧前端项目如何升级工程化的项目
  • 鸿蒙Native使用Demo
  • ubuntu使用Docker,安装,删除,改源等记录
  • 类的加载机制
  • 自制Windows系统(十)
  • Unity 设计模式-单例模式(Singleton)详解
  • 【大数据学习 | Spark-Core】Spark中的join原理
  • 双向链表、循环链表、栈
  • Docker desktop 改变存储位置
  • VUE练习
  • Hive的基础函数
  • 英语知识在线平台:Spring Boot技术探索
  • 流媒体拥塞控制与流控
  • 几个bev模型部署常用的命令
  • 深度学习每周学习总结J6(ResNeXt-50 算法实战与解析 - 猴痘识别)
  • Spring MVC练习(前后端分离开发实例)
  • Linux -线程互斥与同步