代理模式介绍及典型案例

代理模式(Proxy Pattern)是软件设计模式中的一种,它为其他对象提供一个代理以控制对这个对象的访问。在代理模式中,代理类负责为委托类预处理消息、过滤消息、把消息转发给委托类,以及事后处理消息。代理模式可以用来实现延迟加载、日志记录、权限控制等功能。

代理模式的类型

  1. 远程代理(Remote Proxy):为一个位于不同的地址空间的对象提供一个本地的代理对象,这个不同的地址空间可以是在同一台主机上,也可以是在另一台主机上。
  2. 虚拟代理(Virtual Proxy):根据需要创建开销很大的对象,通过使用一个小对象来代表一个大对象,从而减少实际对象的创建次数。
  3. 保护代理(Protection Proxy):控制对原始对象的访问,用于对象有不同的访问权限。
  4. 智能引用(Smart Reference):当一个对象被引用时,提供额外的操作,比如记录对象被访问的次数等。

代理模式的结构

  • Subject(主题接口):定义了RealSubject和Proxy的共同接口,这样在任何使用RealSubject的地方都可以使用Proxy。
  • RealSubject(真实主题):定义了代理所代表的真实对象。
  • Proxy(代理):保存一个引用使得代理可以访问真实主题,并提供一个与Subject相同的接口,以便可以在任何使用RealSubject的地方使用Proxy。代理可以在客户端调用传递给真实主题之前或之后执行一些操作。

代理模式的优缺点

优点

  • 职责分离:将服务对象与调用者分离,增加了系统的灵活性。
  • 控制访问:可以对访问进行控制,例如权限控制、延迟加载等。
  • 增强功能:可以在不改变原始对象的情况下,增加额外的功能,如日志记录、事务处理等。

缺点

  • 复杂度增加:引入代理会使得系统设计更加复杂。
  • 性能影响:如果代理处理不当,可能会导致请求处理速度变慢。

优秀框架案例

  1. Spring AOP(面向切面编程)

    • 介绍:Spring AOP 是 Spring 框架的一部分,用于实现面向切面编程。它允许开发者定义"切面",这些切面可以在多个对象中重用,而无需修改这些对象的代码。Spring AOP 通常用于日志记录、事务管理、安全性等。
    • 实现:Spring AOP 使用代理模式来实现切面。对于 Spring 管理的 Bean,可以使用 CGLIB 代理或 JDK 动态代理。CGLIB 代理适用于没有实现接口的类,而 JDK 动态代理适用于实现了接口的类。
  2. Hibernate 框架

    • 介绍:Hibernate 是一个 ORM(对象关系映射)框架,用于 Java 应用程序。它允许开发者通过 Java 类来管理关系数据库表,并提供了延迟加载功能。
    • 实现:Hibernate 使用代理模式来实现延迟加载。当查询一个对象时,Hibernate 并不会立即加载该对象的所有关联对象,而是返回一个代理对象。只有当访问这些关联对象时,Hibernate 才会真正去数据库中加载数据。
  3. Java RMI(远程方法调用)

    • 介绍:Java RMI 是 Java 平台提供的一个远程过程调用技术,允许一个 Java 虚拟机中的对象调用另一个 Java 虚拟机中的对象的方法。
    • 实现:Java RMI 使用远程代理模式。客户端通过一个远程代理对象来调用服务器端的方法,代理对象负责处理网络通信和方法调用。
  4. Apache Shiro

    • 介绍:Apache Shiro 是一个强大且易用的 Java 安全框架,提供了认证、授权、加密和会话管理功能。
    • 实现:Shiro 使用保护代理模式来控制对资源的访问。通过代理对象,Shiro 可以在用户访问资源之前进行权限检查,确保用户有相应的权限。

示例代码

以下是一个简单的 Java 代理模式示例,使用了 JDK 动态代理:

java 复制代码
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

// 定义一个接口
interface Service {
    void doSomething();
}

// 实现该接口的真实对象
class RealService implements Service {
    @Override
    public void doSomething() {
        System.out.println("RealService is doing something.");
    }
}

// 定义一个代理类,实现了 InvocationHandler 接口
class ServiceProxy implements InvocationHandler {
    private final Service realService;

    public ServiceProxy(Service realService) {
        this.realService = realService;
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        // 在调用真实对象的方法之前,可以添加额外的逻辑
        System.out.println("Before method call.");
        
        // 调用真实对象的方法
        Object result = method.invoke(realService, args);
        
        // 在调用真实对象的方法之后,可以添加额外的逻辑
        System.out.println("After method call.");
        
        return result;
    }
}

public class ProxyPatternExample {
    public static void main(String[] args) {
        // 创建真实对象
        Service realService = new RealService();
        
        // 创建代理对象
        Service proxyService = (Service) Proxy.newProxyInstance(
            RealService.class.getClassLoader(),
            new Class[]{Service.class},
            new ServiceProxy(realService)
        );
        
        // 通过代理对象调用方法
        proxyService.doSomething();
    }
}

在这个示例中,Service 是一个接口,RealService 是实现该接口的真实对象,ServiceProxy 是一个实现了 InvocationHandler 接口的代理类。通过 Proxy.newProxyInstance 方法创建了一个代理对象 proxyService,当调用 proxyService.doSomething() 时,代理对象会在调用真实对象的方法前后添加额外的逻辑。

总结

代理模式是一种非常灵活的设计模式,广泛应用于各种场景中,如远程调用、延迟加载、权限控制等。通过使用代理模式,可以有效地增强系统的功能和灵活性,同时保持原始对象的独立性。

相关推荐
找了一圈尾巴6 小时前
设计模式(结构性)-代理模式
设计模式·代理模式
oracleworm17 小时前
Qt 代理
qt·代理模式
士别三日&&当刮目相看2 天前
JAVA学习*简单的代理模式
java·学习·代理模式
木子庆五2 天前
Android设计模式之代理模式
android·设计模式·代理模式
努力学习的小廉4 天前
【C++】 —— 笔试刷题day_9
开发语言·c++·代理模式
码农幻想梦6 天前
第五章 动态规划
算法·动态规划·代理模式
狮子再回头9 天前
snmp/mib采用子代理模式,编码,部署
代理模式·snmp·mib·snmp子代理
每天减 1/5kg9 天前
结构型——代理模式
python·设计模式·代理模式