什么是代理模式

代理模式(Proxy Pattern)是一种设计模式,它为对象提供一种代理或占位符,通过引入一个代理对象来控制对目标对象的访问。代理对象与目标对象具有相同的接口,客户端可以通过代理对象间接地与目标对象交互。代理模式的主要目的是为了在目标对象的操作前后添加额外的行为,或者为原本难以访问的对象提供访问途径,而不改变客户端代码的调用方式。

代理模式的基本角色如下:

  1. 目标对象(Target):定义了真实业务逻辑的对象,是代理对象所代表的真实对象。它可以是一个接口,也可以是一个具体的类。
  2. 代理对象(Proxy):持有目标对象的引用,提供与目标对象相同的接口。代理对象在执行目标对象方法时,可以添加额外的操作,如预处理、后处理、日志记录、权限检查、缓存、延迟加载等。
  3. 客户端(Client):通过代理对象来调用目标对象的方法。客户端并不关心是直接与目标对象交互还是与代理对象交互,因为它们具有相同的接口。

代理模式有两种常见的实现方式:

1. 静态代理

特点

  • 静态代理在编译期间就已经确定了代理类和目标类的关系,代理类是手动创建的,与目标类一一对应。
  • 静态代理通常用于为单一的目标对象提供代理。

示例

假设有一个Image接口和其实现类RealImage,现在我们创建一个静态代理类ProxyImage来为其提供缓存功能:

复制代码
interface Image {
    void display();
}

class RealImage implements Image {
    private String fileName;

    public RealImage(String fileName) {
        this.fileName = fileName;
        loadFromDisk(fileName); // 加载图片到内存
    }

    private void loadFromDisk(String fileName) {
        // 实际从磁盘加载图片的代码
        System.out.println("Loading image from disk: " + fileName);
    }

    @Override
    public void display() {
        System.out.println("Displaying image: " + fileName);
    }
}

class ProxyImage implements Image {
    private RealImage realImage;
    private String fileName;

    public ProxyImage(String fileName) {
        this.fileName = fileName;
    }

    @Override
    public void display() {
        if (realImage == null) {
            realImage = new RealImage(fileName);
        }
        realImage.display();
    }
}

public class Client {
    public static void main(String[] args) {
        Image proxyImage = new ProxyImage("image.jpg");
        proxyImage.display(); // 第一次调用,从磁盘加载图片
        proxyImage.display(); // 第二次调用,直接从内存中显示图片
    }
}

在这个示例中,ProxyImage作为RealImage的静态代理,实现了相同的Image接口。在display()方法中,如果RealImage尚未创建,则先从磁盘加载图片,然后调用其display()方法。第二次调用时,由于图片已经加载到内存,直接调用RealImagedisplay()方法即可。

2. 动态代理

特点

  • 动态代理在运行时动态地创建代理对象,无需手动编写代理类。
  • 动态代理通常使用反射或字节码技术(如Java的java.lang.reflect.Proxy类或CGLIB库)来创建代理对象。
  • 动态代理可以为一组具有相同接口的目标对象提供代理,具有更好的通用性和灵活性。

示例 (使用Java的java.lang.reflect.Proxy类):

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

interface Image {
    void display();
}

class RealImage implements Image {
    // 同上...
}

class ImageInvocationHandler implements InvocationHandler {
    private Image target;

    public ImageInvocationHandler(Image target) {
        this.target = target;
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        System.out.println("Before displaying the image...");
        Object result = method.invoke(target, args);
        System.out.println("After displaying the image...");
        return result;
    }
}

public class Client {
    public static void main(String[] args) {
        Image realImage = new RealImage("image.jpg");
        Image proxyImage = (Image) Proxy.newProxyInstance(
                Image.class.getClassLoader(),
                new Class[]{Image.class},
                new ImageInvocationHandler(realImage)
        );
        proxyImage.display();
    }
}

在这个示例中,我们使用java.lang.reflect.Proxy类创建了一个动态代理对象proxyImage,它在调用display()方法时,会先执行ImageInvocationHandler中的invoke()方法,添加了显示图片前后的额外操作。ImageInvocationHandler持有RealImage对象的引用,并通过反射调用其display()方法。

总结来说,代理模式通过引入代理对象来控制对目标对象的访问,能够在不修改目标对象代码的前提下,为对象添加额外的行为或提供访问途径。静态代理和动态代理是代理模式的两种实现方式,各有优缺点,适用于不同的应用场景。

相关推荐
柒.梧.7 天前
Java代理模式精讲:静态代理+JDK动态代理
java·开发语言·代理模式
Forget_85508 天前
RHEL——HAProxy模式
代理模式
mjhcsp11 天前
C++ 树形 DP解析
开发语言·c++·动态规划·代理模式
不想看见40411 天前
House Robber 基本动态规划:一维--力扣101算法题解笔记
笔记·算法·leetcode·代理模式
忘梓.13 天前
解锁动态规划的奥秘:从零到精通的创新思维解析(10)
c++·算法·动态规划·代理模式
HEU_firejef16 天前
设计模式——代理模式
设计模式·代理模式
香芋Yu17 天前
【强化学习教程——01_强化学习基石】第03章_动态规划与策略迭代
算法·动态规划·代理模式
J_liaty24 天前
23种设计模式一代理模式
设计模式·代理模式
短剑重铸之日1 个月前
《设计模式》第九篇:三大类型之结构型模式
java·后端·设计模式·组合模式·代理模式·结构性模式
B2_Proxy1 个月前
如何使用代理服务解决“您的 ASN 被阻止”错误:全面策略分析
网络·爬虫·网络协议·tcp/ip·安全·代理模式