代理模式的理解和实践

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

相关推荐
骄马之死5 小时前
SpringMVC + SpringBoot 核心知识点总结
java·spring boot·后端
zhengfei6115 小时前
第3章 Agent 类型分类与设计模式
设计模式
刀法如飞6 小时前
一文搞懂DDD 领域驱动设计思想原理
设计模式·架构·代码规范
郑洁文6 小时前
基于Spring Boot的流浪动物救助网站
java·spring boot·后端·毕设·流浪动物救助
螺丝钉code7 小时前
JAVA项目 Claude code CLAUDE.md 到底应该怎么写
java·人工智能·claude code
摇滚侠8 小时前
Maven 入门+高深 单一架构案例 54-59
java·架构·maven·intellij-idea
VidDown8 小时前
Webhook 调试器:让第三方回调“原形毕露”
java·开发语言·javascript·编辑器·postman
折哥的程序人生 · 物流技术专研9 小时前
Java 23 种设计模式:从踩坑到精通 | 原型模式 —— 克隆对象,深拷贝与浅拷贝的坑你踩过吗?
java·设计模式·架构·原型模式·单一职责原则
装不满的克莱因瓶9 小时前
基于 OpenResty 扩展开发实现动态服务注册与发现能力
java·开发语言·架构·openresty