代理模式的理解和实践

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

相关推荐
S-X-S35 分钟前
算法总结-数组/字符串
java·数据结构·算法
linwq840 分钟前
设计模式学习(二)
java·学习·设计模式
桦说编程1 小时前
CompletableFuture 超时功能有大坑!使用不当直接生产事故!
java·性能优化·函数式编程·并发编程
@_@哆啦A梦1 小时前
Redis 基础命令
java·数据库·redis
字节全栈_rJF2 小时前
性能测试 —— Tomcat监控与调优:status页监控_tomcat 自带监控
java·tomcat
爱编程的小新☆3 小时前
Java篇之继承
java·开发语言
gentle coder3 小时前
Redis_Redission的入门案例、多主案例搭建、分布式锁进行加锁、解锁底层源码解析
java·redis·分布式
Buring_learn3 小时前
代理模式 -- 学习笔记
笔记·学习·代理模式
萝卜青今天也要开心4 小时前
读书笔记-《Redis设计与实现》(一)数据结构与对象(下)
java·数据结构·redis·学习
customer084 小时前
【开源免费】基于SpringBoot+Vue.JS景区民宿预约系统(JAVA毕业设计)
java·vue.js·spring boot·后端·开源