java23种设计模式-代理模式

代理模式(Proxy Pattern)学习笔记

1. 模式定义

结构型设计模式,为其他对象提供一种代理以控制对这个对象的访问。通过引入代理对象,在客户端和目标对象之间起到中介作用。

2. 适用场景

✅ 远程代理(Remote Proxy):为不同地址空间的对象提供代理
✅ 虚拟代理(Virtual Proxy):延迟创建开销大的对象
✅ 保护代理(Protection Proxy):控制不同权限的访问
✅ 智能引用代理(Smart Reference):添加额外操作(如引用计数)
✅ AOP实现、日志记录、事务管理等横切关注点

3. 模式结构

«interface»
Subject
+request()
RealSubject
+request()
Proxy
-realSubject: RealSubject
+request()
+preRequest()
+postRequest()
Client
+doOperation()

4. 核心角色

角色说明
Subject抽象主题接口,声明真实主题和代理的共同接口
RealSubject真实主题类,定义代理所代表的真实对象
Proxy代理类,持有真实主题的引用,提供与真实主题相同的接口
Client客户端,通过代理对象间接访问真实主题

5. 实现方式对比

类型实现方式优点缺点
静态代理手动创建代理类简单直观类膨胀,接口修改需要同步维护
JDK动态代理基于接口,使用ProxyInvocationHandler无需实现大量代理类只能代理接口
CGLIB代理基于字节码生成子类可以代理普通类无法代理final类和方法

6. 代码示例

6.1 静态代理示例

// 抽象主题
interface Image {
    void display();
}

// 真实主题
class RealImage implements Image {
    private String filename;

    public RealImage(String filename) {
        this.filename = filename;
        loadFromDisk();
    }

    private void loadFromDisk() {
        System.out.println("加载图片: " + filename);
    }

    @Override
    public void display() {
        System.out.println("显示图片: " + 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 image = new ProxyImage("test.jpg");
        image.display(); // 真实对象被创建
        image.display(); // 直接使用已创建对象
    }
}

6.2 JDK动态代理示例

import java.lang.reflect.*;

// 抽象主题
interface UserService {
    void addUser(String name);
}

// 真实主题
class UserServiceImpl implements UserService {
    public void addUser(String name) {
        System.out.println("添加用户: " + name);
    }
}

// 代理处理器
class LogHandler implements InvocationHandler {
    private Object target;

    public LogHandler(Object target) {
        this.target = target;
    }

    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        System.out.println("[日志] 方法调用: " + method.getName());
        Object result = method.invoke(target, args);
        System.out.println("[日志] 方法完成: " + method.getName());
        return result;
    }
}

// 客户端
public class Client {
    public static void main(String[] args) {
        UserService realService = new UserServiceImpl();
        UserService proxy = (UserService) Proxy.newProxyInstance(
            realService.getClass().getClassLoader(),
            realService.getClass().getInterfaces(),
            new LogHandler(realService)
        );
        proxy.addUser("张三");
    }
}

7. 模式变种

  1. 远程代理:处理网络通信细节(如RPC调用)
  2. 虚拟代理:延迟加载大资源对象
  3. 防火墙代理:控制网络资源的访问
  4. 同步代理:提供多线程安全访问
  5. 缓存代理:为开销大的运算结果提供缓存

8. 优缺点分析

✔️ 优点

  • 职责清晰,高扩展性
  • 保护真实对象,控制访问细节
  • 降低系统耦合度
  • 支持横切关注点集中处理

缺点

  • 增加系统复杂度
  • 动态代理使用反射影响性能
  • 代理模式可能造成请求处理变慢

9. 相关模式对比

模式目的关键区别
装饰者模式增强功能关注对象功能的增强
适配器模式接口转换主要解决接口不兼容问题
外观模式简化接口组合多个子系统接口

10. 实际应用案例

  • Spring AOP的动态代理实现
  • MyBatis的Mapper接口代理
  • Java RMI远程方法调用
  • Hibernate的延迟加载(Lazy Loading)
  • Servlet的FilterChain
  • Retrofit的网络请求接口

11. 最佳实践建议

  1. 优先使用JDK动态代理(标准库支持)
  2. 需要代理普通类时使用CGLIB
  3. 注意代理方法的性能影响
  4. 避免过度使用导致系统复杂性增加
  5. 使用代理模式实现横切关注点时,结合AOP框架
  6. 对关键业务方法添加访问日志时使用保护代理

🔑 记忆技巧:把代理模式想象成明星的经纪人,客户端(粉丝)通过经纪人(代理)与明星(真实对象)进行互动。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

千里码!

大家互相学习互相资助感谢

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值