代理模式的理解和实践

代理模式(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代码示例,我们可以更好地理解和实践代理模式。

相关推荐
腥臭腐朽的日子熠熠生辉30 分钟前
解决maven失效问题(现象:maven中只有jdk的工具包,没有springboot的包)
java·spring boot·maven
ejinxian31 分钟前
Spring AI Alibaba 快速开发生成式 Java AI 应用
java·人工智能·spring
杉之37 分钟前
SpringBlade 数据库字段的自动填充
java·笔记·学习·spring·tomcat
圈圈编码1 小时前
Spring Task 定时任务
java·前端·spring
俏布斯1 小时前
算法日常记录
java·算法·leetcode
27669582921 小时前
美团民宿 mtgsig 小程序 mtgsig1.2 分析
java·python·小程序·美团·mtgsig·mtgsig1.2·美团民宿
爱的叹息1 小时前
Java 连接 Redis 的驱动(Jedis、Lettuce、Redisson、Spring Data Redis)分类及对比
java·redis·spring
程序猿chen1 小时前
《JVM考古现场(十五):熵火燎原——从量子递归到热寂晶壁的代码涅槃》
java·jvm·git·后端·java-ee·区块链·量子计算
松韬2 小时前
Spring + Redisson:从 0 到 1 搭建高可用分布式缓存系统
java·redis·分布式·spring·缓存
绝顶少年2 小时前
Spring Boot 注解:深度解析与应用场景
java·spring boot·后端