代理模式

尽意
2024-08-21 / 0 评论 / 30 阅读 / 正在检测是否收录...
温馨提示:
本文最后更新于2024年08月21日,已超过154天没有更新,若内容或图片失效,请留言反馈。
代理模式(Proxy Pattern)是设计模式中的一种结构型模式。它为其他对象提供一种代理以控制对这个对象的访问。在 Java 中,代理模式有多种实现方式,主要分为静态代理和动态代理。

1. 代理模式的基本概念

意图:代理模式通过创建一个代理对象来代替实际对象,并且可以控制对实际对象的访问。代理对象和实际对象通常实现相同的接口或继承相同的类。

结构

  • Subject(抽象主题接口/类):定义了真实对象和代理对象的公共接口或父类。
  • RealSubject(真实主题类):实现了抽象主题接口,是代理对象所代表的真实对象。
  • Proxy(代理类):持有一个对真实对象的引用,实现了抽象主题接口,并在调用时对真实对象进行操作。

适用场景

  • 需要对原对象的功能进行扩展或控制,而不改变原对象的代码。
  • 需要对某个类的访问进行控制,比如延迟加载、安全代理、远程代理等。

2. 静态代理

特点:

  • 预先定义:代理类在编译时就已经创建好了,代理类和真实类需要实现相同的接口。
  • 代理行为固定:代理类的行为是静态的,不能在运行时改变。

优缺点:

  • 优点:实现简单,容易理解,能够在编译时进行类型检查。
  • 缺点:代理类与真实类高度耦合,代理类过多会导致代码冗余,不适合扩展性需求高的场景。

示例代码:

// 定义接口
public interface Subject {
    void request();
}

// 真实主题类
public class RealSubject implements Subject {
    @Override
    public void request() {
        System.out.println("真实主题处理请求");
    }
}

// 代理类
public class Proxy implements Subject {
    private RealSubject realSubject;

    public Proxy(RealSubject realSubject) {
        this.realSubject = realSubject;
    }

    @Override
    public void request() {
        System.out.println("代理开始处理");
        realSubject.request();
        System.out.println("代理完成处理");
    }
}

// 测试代码
public class Main {
    public static void main(String[] args) {
        RealSubject realSubject = new RealSubject();
        Proxy proxy = new Proxy(realSubject);
        proxy.request();
    }
}

3. 动态代理

特点:

  • 动态生成:动态代理类在运行时由 JVM 动态生成,不需要事先定义代理类。
  • 灵活性高:可以在运行时灵活地决定代理行为。

实现方式:

  • JDK 动态代理:基于反射机制,只能代理实现了接口的类。
  • CGLIB 动态代理:基于字节码生成,可以代理没有实现接口的类,常用于 Spring 框架。

优缺点:

  • 优点:减少了静态代理的冗余代码,增强了扩展性,可以动态地为多个对象创建代理。
  • 缺点:性能略低于静态代理,调试较为复杂,尤其是对生成的动态代理类进行调试。

JDK 动态代理示例代码:

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

// 定义接口
public interface Subject {
    void request();
}

// 真实主题类
public class RealSubject implements Subject {
    @Override
    public void request() {
        System.out.println("真实主题处理请求");
    }
}

// 动态代理处理器
public class DynamicProxyHandler implements InvocationHandler {
    private Object target;

    public DynamicProxyHandler(Object target) {
        this.target = target;
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        System.out.println("代理开始处理");
        Object result = method.invoke(target, args);  // 调用真实对象的方法
        System.out.println("代理完成处理");
        return result;
    }
}

// 测试代码
public class Main {
    public static void main(String[] args) {
        RealSubject realSubject = new RealSubject();
        Subject proxyInstance = (Subject) Proxy.newProxyInstance(
            realSubject.getClass().getClassLoader(),
            realSubject.getClass().getInterfaces(),
            new DynamicProxyHandler(realSubject)
        );
        proxyInstance.request();
    }
}

4. 代理模式的常见应用

  • 安全代理:控制对原始对象的访问,确保安全性。
  • 延迟加载:在需要时才创建或加载实际对象,以提高性能。
  • 远程代理:为远程对象提供本地代理,使远程调用看起来像本地调用。
  • 虚拟代理:控制对象的访问以延迟实际对象的创建和初始化。
  • 保护代理:通过代理来控制对象的访问权限。

5. 总结

代理模式是一种非常有用的设计模式,它通过引入代理对象来控制对实际对象的访问。静态代理适合简单和固定的场景,而动态代理则提供了更强的灵活性和扩展性。理解代理模式的使用场景和实现方式,可以帮助开发者编写更灵活、更易维护的代码。

4

评论 (0)

取消