代理模式(设计模式)

文章目录

代理模式就是给一个对象提供一个代理,并由代理对象控制对原对象的引用。它使得客户不能直接与真正的目标对象通信。代理对象是目标对象的代表,其他需要与这个目标对象打交道的操作都是和这个代理对象在交涉。
代理对象可以在客户端和目标对象之间起到中介的作用,这样起到了的作用和保护了目标对象的,同时也在一定程度上面减少了系统的耦合度。
代理模式(Proxy Pattern)是一种结构型设计模式,它允许你提供一个代理对象来控制对某个对象的访问。代理模式可以在不改变目标对象的情况下,提供额外的功能或控制。代理模式的主要目的是通过代理对象来间接控制对目标对象的访问,通常用于以下几种场景:
控制对象访问:用于控制对某个对象的访问,例如保护敏感资源。
延迟加载:目标对象的初始化开销较大时,可以通过代理来延迟对象的创建和初始化。
远程代理:为一个位于不同地址空间(如网络)的对象提供本地代表。
虚拟代理:通过使用代理来存放实例化前的开销较大的对象。
日志记录或监控:在访问对象之前或之后添加一些日志记录或监控功能。

代理模式的优点

分离职责:代理模式将具体功能和控制功能分离开,使得代码更加清晰、职责更加明确。

增强功能:可以在不修改目标对象的情况下,通过代理对象增加额外的功能,例如权限控制、延迟加载、日志记录等。

控制访问:可以通过代理对象控制对目标对象的访问,特别是在需要权限验证的场景下非常有用。

代理模式的缺点

增加复杂度:代理模式会引入新的代理类,增加系统的复杂度。

性能开销:由于代理模式需要额外的代理对象,因此会有一定的性能开销,特别是在频繁访问的情况下性能影响更加明显。

代理模式的结构

代理模式主要包含以下几个角色:

抽象主题(Subject):定义了代理类和真实类的共同接口,这样客户端可以通过该接口与代理类进行交互。

真实主题(RealSubject):实现了抽象主题接口,是真正要执行业务逻辑的类。

代理类(Proxy):实现了抽象主题接口,包含对真实主题的引用,实现了对真实主题的控制和访问。

代理模式的UML图

±---------------+ ±---------------+

| Subject |<----------| Proxy |

±---------------+ ±---------------+

| +request() | | -realSubject |

±---------------+ | +request() |

±---------------+

|

v

±---------------+

| RealSubject |

±---------------+

| +request() |

±---------------+

代理模式的类型

  1. 静态代理:由程序员创建或由工具生成代理类文件,在编译时就确定。
  2. 动态代理:在运行时动态生成代理类,不需要预先定义接口。

静态代理

// 抽象主题接口
public interface Subject {
    void request();
}

// 真实主题类
public class RealSubject implements Subject {
    @Override
    public void request() {
        System.out.println("RealSubject: Handling request.");
    }
}

// 代理类
public class Proxy implements Subject {
    private RealSubject realSubject;

    @Override
    public void request() {
        if (realSubject == null) {
            realSubject = new RealSubject();
        }
        System.out.println("Proxy: Logging before request.");
        realSubject.request();
        System.out.println("Proxy: Logging after request.");
    }
}

// 客户端代码
public class Client {
    public static void main(String[] args) {
        Subject proxy = new Proxy();
        proxy.request();
    }
}

动态代理

Java 提供了 java.lang.reflect.Proxy 类和 java.lang.reflect.InvocationHandler 接口来支持动态代理。

代码示例
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

// 抽象主题接口
public interface Subject {
    void request();
}

// 真实主题类
public class RealSubject implements Subject {
    @Override
    public void request() {
        System.out.println("RealSubject: Handling request.");
    }
}

// 动态代理处理器
public class DynamicProxyHandler implements InvocationHandler {
    private Object realSubject;

    public DynamicProxyHandler(Object realSubject) {
        this.realSubject = realSubject;
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        System.out.println("Proxy: Logging before request.");
        Object result = method.invoke(realSubject, args);
        System.out.println("Proxy: Logging after request.");
        return result;
    }
}

// 客户端代码
public class Client {
    public static void main(String[] args) {
        RealSubject realSubject = new RealSubject();
        Subject proxyInstance = (Subject) Proxy.newProxyInstance(
            realSubject.getClass().getClassLoader(),
            realSubject.getClass().getInterfaces(),
            new DynamicProxyHandler(realSubject)
        );

        proxyInstance.request();
    }
}

代理模式的应用场景

远程代理:为一个位于不同地址空间的对象提供局部代表。例如,RMI(远程方法调用)使用了远程代理。

虚拟代理:通过代理来存放实例化前开销较大的对象。例如,图片浏览器使用虚拟代理来延迟加载图像。

保护代理:控制对原始对象的访问。例如,权限控制系统中,对某些操作进行权限检查。

智能指引:在访问对象时执行一些附加操作。例如,在访问数据库连接时,代理模式可以关闭连接。

代理模式是一种非常实用的设计模式,适用于多种场景,通过代理对象来封装和控制对目标对象的访问,使得系统具备更好的扩展性和维护性。

代理模式应用场景

使用场景:Retrofit 中直接调用接口的方法;Spring 的 AOP 机制;

  1. 日志的采集
  2. 权限控制
  3. 实现aop
  4. Mybatis mapper
  5. Spring的事务
  6. 全局捕获异常
  7. Rpc远程调用接口 (传递就是接口)
  8. 代理数据源
    9.自定义注解

动态代理和静态代理的区别

动态代理有别于静态代理,是根据代理的对象,动态创建代理类。这样,就可以避免静态代理中代理类接口过多的问题。动态代理是实现方式,是通过反射来实现的,借助Java自带的java.lang.reflect.Proxy,通过固定的规则生成。

静态代理

静态代理的好处:

可以使真实角色的操作更加纯粹!不用去关注一些公共的业务

公共也就交给代理角色!实现了业务的分工!

公共业务发生扩展的时候,方便集中管理!

缺点:

一个真实角色就会产生一个代理角色:代码量会翻倍-开发效率会变低

动态代理的好处:

可以使真实角色的操作更加纯粹!不用去关注一些公关的业务

公关也就交给代理角色!实现了业务的分工!

公关业务发生扩展的时候,方便集中管理!

一个动态代理类代理的是一个接口,一般就是对应的一类业务

一个动态代理可以代理多个类,只要是实现了同一个接口即可

代理是一种常用的设计模式,目的是:为其他对象提供一个代理以控制对某个对象的访问,

将两个类的关系解耦。代理类和委托类都要实现相同的接口,因为代理真正调用的是委托类的方法。

静态代理开发者自己写代理类 动态代理 不需要开发自己写代码

区别:

1)静态代理:由程序员创建或是由特定工具生成,在代码编译时就确定了被代理的类是哪一个是静态代理。静态代理通常只代理一个类;

2)动态代理:在代码运行期间,运用反射机制动态创建生成。动态代理代理的是一个接口下的多个实现类;

实现步骤:

a.实现 InvocationHandler 接口创建自己的调用处理器;

b.给 Proxy 类提供ClassLoader 和代理接口类型数组创建动态代理类;

c.利用反射机制得到动态代理类的构造函数;

d.利用动态代理类的构造函数创建动态代理类对象;

相关推荐
zzzhpzhpzzz2 小时前
设计模式——前端控制器模式
设计模式
forestsea2 小时前
【Java 解释器模式】实现高扩展性的医学专家诊断规则引擎
java·人工智能·设计模式·解释器模式
小白不太白9504 小时前
设计模式之 命令模式
设计模式·命令模式
吃汉堡吃到饱5 小时前
【创建型设计模式】单例模式
单例模式·设计模式
小白不太白9505 小时前
设计模式之 备忘录模式
服务器·设计模式·备忘录模式
zzzhpzhpzzz5 小时前
设计模式——策略模式
设计模式·策略模式
入门到跑路5 小时前
【君正T31开发记录】8.了解rtsp协议及设计模式
网络协议·设计模式
小白不太白9505 小时前
设计模式之 解释器模式
java·设计模式·解释器模式
小白不太白9506 小时前
设计模式之 代理模式
设计模式·代理模式
吃汉堡吃到饱6 小时前
【创建型设计模式】工厂模式
设计模式