代理模式的理解和实践

代理模式(Proxy Pattern)是一种结构型设计模式,它允许你为其他对象提供一种代理以控制对这个对象的访问。代理对象在客户端和目标对象之间起到中介的作用,客户端通过代理对象间接地访问目标对象。通过这种方式,代理模式可以在不修改目标对象的前提下,为目标对象添加额外的功能或控制访问权限。

本文将详细介绍代理模式的概念、种类、优缺点,并通过Java代码示例展示如何在实践中应用代理模式。

一、代理模式的概念

  1. 定义:代理模式为其他对象提供一种代理,以控制对这个对象的访问。代理对象在客户端和目标对象之间起到中介的作用,客户端通过代理对象间接地访问目标对象。

  2. 结构

    • Subject:抽象主题角色,声明了代理和真实对象的共同接口。
    • RealSubject:真实主题角色,实现了抽象主题接口,是代理对象所代表的真实对象。
    • Proxy:代理角色,持有一个真实对象的引用,可以控制对真实对象的访问,也可以附加额外的功能。
  3. 种类

    • 静态代理:代理类在编译时就确定下来,代理类和目标类的关系在运行前就已经确定,且不可改变。
    • 动态代理:代理类在运行时由JVM根据反射机制动态生成,代理类和目标类的关系在运行时确定。

二、静态代理的理解和实践

静态代理通过定义一个代理类,并在代理类中调用目标对象的方法来实现。这种方式需要在编译时就确定代理类。

示例代码

定义抽象主题接口

java 复制代码
// 抽象主题接口
public interface Image {
    void display();
}

实现真实主题类

java 复制代码
// 真实主题类
public 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 " + filename);
    }

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

定义代理类

java 复制代码
// 代理类
public 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();
    }
}

客户端代码

java 复制代码
public class Client {
    public static void main(String[] args) {
        Image image = new ProxyImage("test.jpg");

        // 图像将从磁盘加载并显示
        image.display();
    }
}

在这个示例中,ProxyImageRealImage 的代理类,它持有一个 RealImage 的引用,并在需要时才加载真实的图像对象。通过这种方式,可以在不修改 RealImage 的前提下,为其添加懒加载功能。

三、动态代理的理解和实践

动态代理通过Java反射机制在运行时动态生成代理类,而不需要在编译时确定代理类。Java提供了 java.lang.reflect.Proxy 类和 java.lang.reflect.InvocationHandler 接口来实现动态代理。

示例代码

定义抽象主题接口

java 复制代码
// 抽象主题接口
public interface Image {
    void display();
}

实现真实主题类

java 复制代码
// 真实主题类
public 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 " + filename);
    }

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

定义动态代理处理器

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

// 动态代理处理器
public class ImageInvocationHandler implements InvocationHandler {
    private Object realObject;

    public ImageInvocationHandler(Object realObject) {
        this.realObject = realObject;
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        if ("display".equals(method.getName())) {
            System.out.println("Proxy: Loading image proxy...");
            Object result = method.invoke(realObject, args);
            return result;
        }
        return null;
    }
}

客户端代码

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

public class Client {
    public static void main(String[] args) {
        Image realImage = new RealImage("test.jpg");
        Image proxyInstance = (Image) Proxy.newProxyInstance(
                realImage.getClass().getClassLoader(),
                realImage.getClass().getInterfaces(),
                new ImageInvocationHandler(realImage)
        );

        // 图像将通过代理加载并显示
        proxyInstance.display();
    }
}

在这个示例中,ImageInvocationHandler 是动态代理处理器,它实现了 InvocationHandler 接口。Proxy.newProxyInstance 方法在运行时动态生成代理类,并返回一个实现了 Image 接口的代理对象。客户端通过代理对象调用 display 方法时,会触发 ImageInvocationHandlerinvoke 方法,从而实现对真实对象的访问控制。

四、代理模式的优缺点

优点

  1. 增强功能:代理模式可以在不修改目标对象的前提下,为目标对象添加额外的功能。
  2. 控制访问:代理模式可以控制对目标对象的访问权限,例如限制访问次数或时间。
  3. 缓存和懒加载:代理模式可以实现缓存和懒加载机制,提高系统的性能和资源利用率。

缺点

  1. 复杂性:代理模式增加了系统的复杂性,特别是当代理类较多时,代码会变得难以维护。
  2. 性能开销:代理模式在客户端和目标对象之间增加了一层中介,可能会引入额外的性能开销。

总结

代理模式是一种结构型设计模式,它允许你为其他对象提供一种代理以控制对这个对象的访问。代理模式可以在不修改目标对象的前提下,为目标对象添加额外的功能或控制访问权限。静态代理和动态代理是代理模式的两种实现方式,静态代理在编译时确定代理类,而动态代理在运行时动态生成代理类。通过Java代码示例,我们可以更好地理解和实践代理模式。

相关推荐
颜如玉14 分钟前
🤲🏻🤲🏻🤲🏻临时重定向一定要能重定向🤲🏻🤲🏻🤲🏻
java·http·源码
程序员的世界你不懂1 小时前
【Flask】测试平台开发,新增说明书编写和展示功能 第二十三篇
java·前端·数据库
星空寻流年1 小时前
设计模式第一章(建造者模式)
java·设计模式·建造者模式
gb42152872 小时前
java中将租户ID包装为JSQLParser的StringValue表达式对象,JSQLParser指的是?
java·开发语言·python
曾经的三心草3 小时前
Python2-工具安装使用-anaconda-jupyter-PyCharm-Matplotlib
android·java·服务器
蒋星熠3 小时前
Flutter跨平台工程实践与原理透视:从渲染引擎到高质产物
开发语言·python·算法·flutter·设计模式·性能优化·硬件工程
Metaphor6923 小时前
Java 高效处理 Word 文档:查找并替换文本的全面指南
java·经验分享·word
ChinaRainbowSea3 小时前
7. LangChain4j + 记忆缓存详细说明
java·数据库·redis·后端·缓存·langchain·ai编程
stormsha3 小时前
飞算JavaAI炫技赛电商系统商品管理模块的架构设计与实现
java·架构·鸿蒙系统
minh_coo3 小时前
Spring框架事件驱动架构核心注解之@EventListener
java·后端·spring·架构·intellij-idea