设计模式:代理模式 ⑦

news2025/1/13 3:08:13

一、核心思想

                调用方 --> 代理 ---> 目标对象

                代理是调用真实目标对象的一层中间层,如果需要进行

                        ①、屏蔽复杂对象的创建过程,让上层调用友好感知,并起到隐藏保护的目的。

                        ②、一定的方法扩展增强           

                        ③、或者在对目标对象调用时,做一些权限前置校验。

二、静态代理,JDK和CGLIB动态代理   

       代理模式结构:

        其中,Client是客户端类,它需要使用Subject接口提供的方法。Proxy是代理类,它持有一个RealSubject的引用,并且实现了Subject接口。RealSubject是真实类,它也实现了Subject接口,并且定义了具体的业务逻辑。

        代理模式有多种类型,例如静态代理、动态代理等,代理模式也有自己的优缺点,使用时需要根据具体的场景和需求来选择合适的类型和方式。

静态代理实现

        下面我们用Java代码来实现一个静态代理的例子:

// 抽象主题接口
public interface Subject {
    // 定义一个抽象方法
    void request();
}
​
// 真实主题类
public class RealSubject implements Subject {
    // 实现抽象方法
    @Override
    public void request() {
        // 真实的业务逻辑
        System.out.println("RealSubject is doing something...");
    }
}
​
// 代理主题类
public class Proxy implements Subject {
    // 持有一个真实主题的引用
    private RealSubject realSubject;
​
    // 构造方法,传入一个真实主题对象
    public Proxy(RealSubject realSubject) {
        this.realSubject = realSubject;
    }
​
    // 实现抽象方法
    @Override
    public void request() {
        // 在调用真实主题之前,可以执行一些额外操作
        System.out.println("Proxy is doing something before...");
        // 调用真实主题的方法
        realSubject.request();
        // 在调用真实主题之后,可以执行一些额外操作
        System.out.println("Proxy is doing something after...");
    }
}
​
// 客户端类
public class Client {
    public static void main(String[] args) {
        // 创建一个真实主题对象
        RealSubject realSubject = new RealSubject();
        // 创建一个代理对象,并传入真实主题对象
        Proxy proxy = new Proxy(realSubject);
        // 使用代理对象来调用抽象方法
        proxy.request();
    }
}
运行结果如下:
Proxy is doing something before...
RealSubject is doing something...
Proxy is doing something after...

        从运行结果可以看出,代理对象在调用真实对象的方法之前和之后,都执行了一些额外的操作,从而对真实对象进行了增强或控制。

        动态代理实现

        动态代理是一种特殊的代理模式,它可以在运行时动态地创建代理对象,而不需要事先定义代理类。动态代理可以更灵活地适应不同的场景和需求,但是也更复杂和难以理解。

        这个例子是使用JDK动态代理来实现一个日志代理,它可以在调用目标对象的方法之前和之后,记录相关的日志信息。代码如下:

// 抽象主题接口
public interface Subject {
    // 定义一个抽象方法
    void request();
}
​
// 真实主题类
public class RealSubject implements Subject {
    // 实现抽象方法
    @Override
    public void request() {
        // 真实的业务逻辑
        System.out.println("RealSubject is doing something...");
    }
}
​
// 日志处理器类,实现了InvocationHandler接口,用于定义代理逻辑
public class LogHandler implements InvocationHandler {
    // 持有一个目标对象的引用
    private Object target;
​
    // 构造方法,传入一个目标对象
    public LogHandler(Object target) {
        this.target = target;
    }
​
    // 实现invoke方法,用于调用目标对象的方法,并在之前和之后执行日志操作
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        // 在调用目标对象之前,记录开始时间
        long startTime = System.currentTimeMillis();
        System.out.println("开始执行" + method.getName() + "方法...");
        // 调用目标对象的方法,并获取返回值
        Object result = method.invoke(target, args);
        // 在调用目标对象之后,记录结束时间和耗时
        long endTime = System.currentTimeMillis();
        long duration = endTime - startTime;
        System.out.println("结束执行" + method.getName() + "方法,耗时" + duration + "毫秒");
        // 返回结果
        return result;
    }
}
​
// 客户端类
public class Client {
    public static void main(String[] args) {
        // 创建一个真实主题对象
        RealSubject realSubject = new RealSubject();
        // 创建一个日志处理器对象,并传入真实主题对象
        LogHandler logHandler = new LogHandler(realSubject);
        // 使用Proxy类的静态方法newProxyInstance来动态地创建一个代理对象,传入真实主题对象的类加载器、接口和处理器
        Subject proxy = (Subject) Proxy.newProxyInstance(realSubject.getClass().getClassLoader(), realSubject.getClass().getInterfaces(), logHandler);
        // 使用代理对象来调用抽象方法
        proxy.request();
    }
}

运行结果如下:

开始执行request方法...
RealSubject is doing something...
结束执行request方法,耗时1毫秒

        从运行结果可以看出,代理对象在调用真实对象的方法之前和之后,都执行了一些日志操作,从而对真实对象进行了增强。

        CGLIB代理

                Java中的三种代理模式详解_java_脚本之家

                ​​​​​​​Java设计模式-代理模式 - 知乎

        

三、优缺点

        优点:

                代理的目的更多的是一种对目标对象的隐藏或者是一些行为的增强。

        缺点:

                非直连创建对象,多一个中间环节,就多了一个份资源的消耗。

三、运用场景

  • 网络层面:负载的代理  --》当我们需要访问一个远程对象时,可以使用远程代理,它可以隐藏远程对象的位置和通信细节,让客户端像访问本地对象一样访问远程对象。
  • 当我们需要创建一个开销很大的对象时,可以使用虚拟代理,它可以在真正需要的时候才创建真实对象,从而实现延迟加载和节省资源。RabbitMQ缓冲处理信息代理
  • 当我们需要给一个对象增加一些额外的功能时,可以使用装饰代理,它可以在不修改原有对象的情况下,给对象添加一些新的行为或属性。
  • 当我们需要给一个对象增加一些访问控制或安全保护时,可以使用保护代理,它可以根据不同的用户或角色,对对象的访问进行限制或检查。
  • 当我们需要给一个对象增加一些日志记录或性能监控时,可以使用日志代理或性能代理,它可以在调用对象的方法之前或之后,记录相关的信息或数据。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1493177.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

2024.03.05作业

select实现tcp并发服务器 #include "test.h"#define SER_IP "192.168.42.106" #define SER_PORT 8888int create_socket() {int sfd socket(AF_INET, SOCK_STREAM, 0);if(sfd -1){perror("socket error");exit(-1);}printf("sfd %d\n&q…

如何使用Python操作MySQL的各种功能?高级用法?

当今互联网时代,数据处理已经成为了一个非常重要的任务。而MySQL作为一款开源的关系型数据库,被广泛应用于各种场景。本篇博客将介绍如何使用Python操作MySQL的各种功能,以及一些高级用法。 连接MySQL 在Python中,我们可以使用p…

《操作系统真相还原》读书笔记二:环境搭建 xshell连接virtualbox

修改 sshd_config 使用 vi /etc/ssh/sshd_config命令进入sshd服务配置,键盘输入i进行编辑,将监听端口、监听地址前的 # 号去除,开启允许远程登录,开启使用用户名密码来作为连接验证。修改完成,按一下Esc,输…

汽车级瞬态抑制TVS二极管优势特性及型号大全

汽车级瞬态抑制TVS二极管是一种高性能的防浪涌过电压电路保护元器件,能够在瞬态电压过高的情况下提供可靠的保护。它能够迅速响应并吸收过电压,将其导向地线,从而保护车辆的电子设备免受损坏。东沃汽车级TVS二极管具有以下几个关键优势&#…

安卓Activity的深度探索:任务栈管理、启动模式及屏幕旋转策略的分析与应用

摘要 本文旨在深入探讨安卓Activity作为Android应用架构基石的重要概念,集中研究其任务栈管理机制、启动模式以及对屏幕旋转事件的响应策略。通过对这些核心特性的详尽阐述、优劣分析以及优化方案的讨论,为开发者优化用户体验、提升应用性能提供理论指导…

蓝牙系列二:BLE协议各层的形象化理解

对于蓝牙的协议栈模型已经不再陌生,但是看过相关的文档还是有些没法理解协议栈每层的区别以及每层的功能作用。本文还是继续学习韦东山讲解的蓝牙,对于初学者还是有很好的帮助作用,下面是韦东山老师形象化协议栈的框图: 下面还是把…

[java] 23种设计模式之责任链模式

1.1例子 公司请假系统,业务逻辑如下: 不超过3天的,组长审批 超过3天且小于7天的,总监审批 超过7天且小于15天的,部长审批 超过15天,前端直接拒绝,不会进入审批流程(违反了公司的请假…

GIS之深度学习06:CUDA12安装(适配版)

CUDA(Compute Unified Device Architecture)是NVIDIA开发的并行计算平台和编程模型,用于利用NVIDIA GPU的并行计算能力,它允许开发者使用类似于C语言的编程语言编写并行程序,利用GPU的大规模并行计算能力加速各种类型的…

three.js如何实现简易3D机房?(一)基础准备-下

接上一篇&#xff1a; three.js如何实现简易3D机房&#xff1f;&#xff08;一&#xff09;基础准备-上&#xff1a;http://t.csdnimg.cn/MCrFZ 目录 四、按需引入 五、导入模型 四、按需引入 index.vue文件中 <template><div class"three-area">&l…

OJ习题之——圆括号编码

圆括号编码 1.题目描述2.完整代码3.图例演示 1.题目描述 题目描述 令Ss1 s2 …sn是一个规则的圆括号字符串。S以2种不同形式编码&#xff1a; &#xff08;1&#xff09;用一个整数序列Pp1 p2 … pn编码&#xff0c;pi代表在S中第i个右圆括号的左圆括号数量。&#xff08;记为…

一本书讲透ChatGPT,实现从理论到实践的跨越!大模型技术工程师必读

程序员如何选择职业赛道&#xff1f; 文章目录 程序员如何选择职业赛道&#xff1f;前言**作者简介**目录直播预告 前言 OpenAI 在 2022 年 11 月推出了人工智能聊天应用—ChatGPT。它具有广泛的应用场景&#xff0c;在多项专业和学术基准测试中表现出的智力水平&#xff0c;不…

esp32 C3和S3 开发板电流对比

出去好奇用合宙家的 lot power 测了两块开发板的运行电流。 esp32 S3 (嘉立创开发板 8N8 版本) 模式 电流downloa模式49 毫安空代码91 毫安light mode27 毫安deep mode25 毫安delay 40 毫安 esp32 C3 无串口芯片 &#xff08;合宙 9.9 元版本&#xff09; 模式 …

E33NCHA-LNN-NS-00主要特点

E33NCHA-LNN-NS-00是一款由Kollmorgen公司生产的高性能伺服电机&#xff0c;专门设计用于对运动系统进行精确控制。 以下是这款伺服电机的一些主要特点&#xff1a; 高扭矩密度&#xff1a;该电机能够在其尺寸下提供较大的扭矩输出&#xff0c;这对于空间有限的应用场合尤为重…

rocketmq Listener 消费消息的优雅方式(基于SPEL)

DefaultMQPushConsumer 配置 package repayment.config;import cn.itcast.wanxinp2p.repayment.message.diy.DefaultMessageListenerConcurrently; import org.apache.rocketmq.client.consumer.DefaultMQPushConsumer; import org.apache.rocketmq.client.exception.MQClient…

go语言基础 -- 文件操作

基础的文件操作方法 go里面的文件操作封装在os包里面的File结构体中&#xff0c;要用的时候最好去查下官方文档&#xff0c;这里介绍下基本的文件操作。 打开关闭文件 import("os" ) func main() {// Open返回*File指针&#xff0c;后续的操作都通过*File对象操作…

【XR806开发板试用】第一篇-基于ArchLinux配置开发环境并烧录

前段时间很幸运的申请到了XR806的这块开发板子。由于出差、生病还有各种事情的影响&#xff0c;这周末才有空拿出来收到的板子把玩一番。前段时间也抽空看了看其他工程师的体验文章。初步了解到全志为这块板子提供了比较方便的Linux开发环境。嗯&#xff0c;毕竟搞嵌入式嘛&…

Python乱码恢复

比如说网页是ISO-8859-1编码&#xff0c;然后requests得到的是乱码&#xff0c; 那么这样操作就可以还原数据&#xff1a;res.text.encode(‘ISO-8859-1’).decode(‘utf-8’) 乱码恢复网站&#xff0c;可以知道是什么编码http://www.mytju.com/classCode/tools/messyCodeReco…

【深度学习笔记】计算机视觉——风格迁移

风格迁移 摄影爱好者也许接触过滤波器。它能改变照片的颜色风格&#xff0c;从而使风景照更加锐利或者令人像更加美白。但一个滤波器通常只能改变照片的某个方面。如果要照片达到理想中的风格&#xff0c;可能需要尝试大量不同的组合。这个过程的复杂程度不亚于模型调参。 本…

2024-阿里巴巴灵犀互娱校招内推

灵犀互娱是阿里集团旗下研运一体游戏品牌&#xff0c;在业务模式上&#xff0c;灵犀互娱面向全球&#xff0c;研运一体&#xff0c;坚持精品&#xff0c;打造爆款&#xff0c;重视服务玩家。 访问链接即刻开启内推&#xff1a;https://talent.lingxigames.com/campus/qrcode/…

第十二篇:学习python数据清洗

文章目录 一、啥是数据清洗二、将表格数据导入pandas中1. 准备工作2. 引入csv文件2.1 引入pandas库2.2 读取文件/修改名称3.2 快速浏览数据2.4 修改名字2.5 查找缺失值2.6 删除缺失值 3. 引入Excel文件3.1 引入pandas库3.2 读取Excel文件的人均GDP数据3.3 查看数据类型和non-nu…