设计模式——代理模式

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档

文章目录


前言

  • 某个客户端不能直接操作到某个对象,但又必须和那个对象有所互动
    • 如果对象是一个大图片,需要花费很长时间才能显示出来,此时需要做个图片Proxy来代替真正的图片。
    • 如果对象在某远端服务器上,直接操作这个对象因为网络速度原因可能比较慢,那么可以先用Proxy来代替那个对象。

1、定义

代理模式是为其他对象提供一种代理以控制对这个对象的访问。

代理模式的主要作用是扩展目标对象的功能,比如说在目标对象的某个方法执行前后可以增加一些自定义的操作。

2、结构


代理模式的参与者:

  • Proxy:代理主题角色
    • 保存一个引用使得代理可以访问实体
    • 提供一个与Subject的相同的接口,这样代理就可以用来替代实体。
    • 控制对实体的存取,并可能负责创建和删除它。
    • 其他功能依赖于代理的类型。
  • Subject:抽象主题角色
    • 定义ConcreteSubject和Proxy的共用接口,在任何使用ConcreteSubject的敌方都可以使用Proxy。
  • RealSubject:真实主题角色
    • 定义Proxy所代表的实体

3、实现方式

3.1 静态代理

实现流程:

1、定义一个接口及实现类

2、创建一个代理类同样实现这个接口

3、将目标对象注入进代理类,然后在代理类的对应方法调用目标类中的对应方法

以短信发送为例:
步骤1如下:

java 复制代码
public interface SmsService {
    /**
     * 发送短信
     * @param phone 手机号(如+8613812345678)
     * @param params 模板参数
     * @return 是否发送成功
     */
    boolean sendSms(String phone, String[] params);
} 
java 复制代码
@Service
public class SmsServiceImpl implements SmsService {

    @Override
    public boolean sendSms(String phone, String[] params) {
        // 实现发送短信的方法
    }
} 

步骤2如下:

java 复制代码
public class SmsProxy implements SmsService {

    private final SmsService smsService;

    public SmsProxy(SmsService smsService) {
        this.smsService = smsService;
    }

    @Override
    public String send(String message) {
        System.out.println("before method send()");
        smsService.sendSms(message);
        System.out.println("after method send()");
        return null;
    }
}

3.2 动态代理

动态代理不需要针对每个目标类都单独创建一个代理类,并且也不需要必须实现接口,可以直接代理实现类。

从JVM角度来说,动态代理是在运行时动态生成类字节码,并加载到JVM中的。

Spring AOP、RPC框架实现都依赖了动态代理

3.2.1 JDK动态代理

Java动态代理机制中,InvocationHander接口和proxy类是核心

Proxy类中使用频率最高的方法是newProxyInstance(),这个方法主要用来生成一个代理对象。

java 复制代码
    public static Object newProxyInstance(ClassLoader loader,
                                          Class<?>[] interfaces,
                                          InvocationHandler h)
        throws IllegalArgumentException
    {
        ......
    }
  • loader:类加载器,用于加载代理对象
  • interfaces:被代理类实现的一些接口
  • h:实现了InvocationHandler接口的对象

要实现动态代理,必须要实现InvocationHandler来自定义处理逻辑。当动态代理调用一个方法时,这个方法的调用就会被转发到实现InvocationHandler接口类的invoke方法来调用。

java 复制代码
public interface InvocationHandler {

    /**
     * 当你使用代理对象调用方法的时候实际会调用到这个方法
     */
    public Object invoke(Object proxy, Method method, Object[] args)
        throws Throwable;
}

invoke()方法有3个参数:

  • proxy:动态生成的代理类
  • method:与代理类对象调用的方法相对应
  • args:当前method方法的参数

3.2.2 CGLIB动态代理

CGLIB是一个基于ASM的字节码生成库,它允许在运行时对字节码进行修改和动态生成。CGLIB通过继承方式实现代理。


总结

相关推荐
Coder_Boy_3 小时前
从单体并发工具类到分布式并发:思想演进与最佳实践(二)
java·spring boot·分布式·微服务·设计模式
geovindu12 小时前
python: Memento Pattern
开发语言·python·设计模式·备忘录模式
HEU_firejef21 小时前
设计模式——单例模式
单例模式·设计模式
电子科技圈1 天前
SmartDV与Mirabilis Design宣布就SmartDV IP系统级模型达成战略合作
大数据·设计模式·软件工程
带娃的IT创业者1 天前
解密OpenClaw系列04-OpenClaw设计模式应用
设计模式·软件工程·软件架构·ai agent·ai智能体开发·openclaw
kong79069281 天前
设计模式-策略模式
设计模式·策略模式·行为设计模式
香芋Yu1 天前
【强化学习教程——01_强化学习基石】第03章_动态规划与策略迭代
算法·动态规划·代理模式
全栈前端老曹2 天前
【Redis】发布订阅模型 —— Pub/Sub 原理、消息队列、聊天系统实战
前端·数据库·redis·设计模式·node.js·全栈·发布订阅模型
资深web全栈开发2 天前
设计模式之桥接模式 (Bridge Pattern)
javascript·设计模式·桥接模式