设计模式之代理模式(静态代理动态代理)
目录
1、什么是代理模式
2、代理模式的结构
3、代理模式的实现
3.1 静态代理和动态代理概念
3.2 静态代理
3.3 动态搭理
3.3.1 代码实现
3.3.2 Proxy类讲解
4、动态代理VS静态代理
5、代理模式优缺点
1、什么是代理模式
由于某些原因需要给某对象提供一个代理以控制对该对象的访问。这时,访问对象不适合或者不能直接引用目标对象,代理对象作为访问对象和目标对象之间的中介。
2、代理模式的结构
代理(Proxy)模式分为三种角色:
- 抽象主题(Subject)类: 通过接口或抽象类声明真实主题和代理对象实现的业务方法。
- 真实主题(Real Subject)类: 实现了抽象主题中的具体业务,是代理对象所代表的真实对象,是最终要引用的对象。
- 代理(Proxy)类 : 提供了与真实主题相同的接口,其内部含有对真实主题的引用,它可以访问、控制或扩展真实主题的功能。
3、代理模式的实现
3.1 静态代理和动态代理概念
Java中的代理按照代理类生成时机不同又分为静态代理和动态代理。静态代理代理类在编译期就生成,而动态代理代理类则是在Java运行时动态生成。动态代理又有JDK代理和CGLib代理两种。
(本文中的动态代理主要讲解的是JDK代理,如果大家对CGLib代理感兴趣的话可以自行查阅网上的文章)
3.2 静态代理
我们直接通过案例来感受一下动态代理,以下是场景描述:
一般明星(对象本身)都会有一个经纪人(代理对象)来帮他处理一些事情,比如明星开演唱会之前收门票费用,预约场地,演唱会结束之后调查观众对该演唱会的反馈之类的事情肯定不能交给大明星做吧,所以这些事情一般都是交给经纪人去处理。
这个例子就是一个典型的代理例子,因此我们来看看通过静态代理如何实现:
明星类(抽象主题类):
public interface bigStar {//抽象主题类String Sing();void Dance();
}
坤坤类(真实主题类):
public class KunKun implements bigStar{ //真实主题类public String Sing(){System.out.println("大明星:坤坤开始唱歌");return "鸡你太美"; //返回歌词}public void Dance(){System.out.println("大明星:坤坤开始跳舞");}
}
经纪人类(代理类):
public class StaticProxy implements bigStar{ //代理类private bigStar star;public StaticProxy(bigStar bigStar){star=bigStar;}@Overridepublic String Sing() {System.out.println("唱歌前收取门票费用、预约场地");String sing = star.Sing();System.out.println("唱歌结束后帮忙调查观众反馈");return sing;}@Overridepublic void Dance() {System.out.println("跳舞前收取门票费用、预约场地");star.Dance();System.out.println("跳舞结束后帮忙调查观众反馈");}
}
测试类:
public class Test {public static void main(String[] args) {KunKun kunKun = new KunKun();StaticProxy proxy = new StaticProxy(kunKun);proxy.Dance();System.out.println("------");String sing = proxy.Sing();System.out.println("歌词为:"+sing);}
}
运行结果如下:
可见,我们通过“静态代理”的方式实现了“代理模式”,成功在“坤坤”唱歌、跳舞前做好了准备工作以及在结束后做好了调查观众反馈的工作。这些都是代理类来完成的,看到这里大家肯定意识到了代理模式的一个好处就是:“在被代理对象方法执行前后能做一定的处理、加强”。
但是上述静态代理模式有没有缺点呢?
有!而且很明显!那就是:“杂!乱!如果接口增加一个方法,静态代理模式除了所有实现类需要实现这个方法外,所有代理类也需要实现此方法。增加了代码维护的复杂度。”
因此,我们引出另一种实现代理模式的方法:“动态代理”。
3.3 动态搭理
3.3.1 代码实现
动态代理的JDK代理实现主要是通过“Proxy类”来实现的,我们直接来看代码实现,大家耐心看,代码里面有很详细的注释。看不懂可以先看底下对于里面参数的讲解部分。
大明星类(抽象主题类):
public interface bigStar { //大明星类(抽象主题类)public String Sing();public void Dance();
}
坤坤类(真实主题类):
public class KUN implements bigStar { //坤坤类(真实主题类)@Overridepublic String Sing() {System.out.println("坤坤在唱歌......");//返回歌词return "鸡你太美";}@Overridepublic void Dance() {System.out.println("坤坤在跳舞");}
}
经纪人(代理类):
public class StarProxyFactory { //经纪人(代理类)public static bigStar getProxy(bigStar star){bigStar result=(bigStar)Proxy.newProxyInstance( //newProxyInstance()方法即返回代理对象
// newProxyInstance()方法参数说明:
// ClassLoader loader : 类加载器,用于加载代理类,使用真实对象的类加载器即可
// Class<?>[] interfaces : 真实对象所实现的接口,代理模式真实对象和代理对象实现相同的接口
// InvocationHandler h : 代理对象的调用处理程序star.getClass().getClassLoader(),star.getClass().getInterfaces(),new InvocationHandler() {@Override
// InvocationHandler中invoke方法参数说明:
// proxy:代理对象
// method:对应于在代理对象上调用的接口方法的 Method 实例,比如我们调用了“Sing()”这个方法,那么对应的就是“Sing()”的Method实例
// args:对应我们方法传入的参数public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {System.out.println("场地布置、收取门票费用");Object invoke = method.invoke(star, args);System.out.println("场地打扫");return invoke; //返回方法调用结果}});return result;}
}
测试类:
public class Test {public static void main(String[] args) {KUN kun = new KUN();bigStar proxy = StarProxyFactory.getProxy(kun);//获取动态代理对象//验证是否被代理proxy.Dance();System.out.println("--------------");String sing = proxy.Sing();System.out.println("歌词为:"+sing);}
}
运行结果如下:
可见,我们通过Java提供的“Proxy类”也实现了代理的效果,但是大家看完可能会一脸懵逼,发生了什么?我在哪?我是谁?
因此接下来我们对“Proxy类”这个类做一个详细的解释。
3.3.2 Proxy类讲解
首先,我们刚刚是通过Proxy.newProxyInstance()来获取一个代理对象,它所需要的参数如下:
可见,我们如果使用Proxy.newProxyInstance()的话,需要对它传入以下参数:
①参数一:指类加载器,意思是需要我们告诉它我们需要用哪个类加载器去加载代理对象,通常我们代理对象与被代理对象可以使用同一个类加载器,因此比如上文我们是代理star对象,因此我们传入的类加载器就是:“star.getClass().getClassLoader()”。
②参数二:指真实对象所实现的接口,代理模式真实对象和代理对象实现相同的接口,因此我们也直接传入真实对象的接口即可:“star.getClass().getInterfaces()”。
③参数三:指代理对象最终调用的程序,一般代理对象调用某个方法后,都会走我们参数三写的这个方法,大家往回看代码会发现我们参数三传入了一个匿名内部类对象“new InvocationHandler()”
大家又可以发现,这个“InvocationHandler类”创建对象时,要求重写里面的invoke方法:
我们再来逐一说说这几个参数的作用:
- proxy:代理对象本身
- method:对应于在代理对象上调用的接口方法的 Method 实例,比如我们调用了“Sing()”这个方法,那么对应的就是“Sing()”的Method实例
- args:对应我们方法传入的参数
因此呢,我们可以在invoke方法里面做一些方法加强(比如我们之前的代码),也就是我们的“代理”。
以上便是动态代理实现代理模式的代码。
4、动态代理VS静态代理
动态代理与静态代理相比较,最大的好处是接口中声明的所有方法都被转移到调用处理器一个集中的方法中处理(InvocationHandler.invoke)。这样,在接口方法数量比较多的时候,我们可以进行灵活处理,而不需要像静态代理那样每一个方法进行中转。
如果接口增加一个方法,静态代理模式除了所有实现类需要实现这个方法外,所有代理类也需要实现此方法。增加了代码维护的复杂度。而动态代理不会出现该问题
5、代理模式优缺点
优点:
- 代理模式在客户端与目标对象之间起到一个中介作用和保护目标对象的作用。
- 代理对象可以扩展目标对象的功能。
- 代理模式能将客户端与目标对象分离,在一定程度上降低了系统的耦合度。
缺点:
- 增加了系统的复杂度。
以上是代理模式的详解,大家麻烦点个赞和关注可以嘛!现在点关注就是老粉啦!
相关文章:
设计模式之代理模式(静态代理动态代理)
目录 1、什么是代理模式 2、代理模式的结构 3、代理模式的实现 3.1 静态代理和动态代理概念 3.2 静态代理 3.3 动态搭理 3.3.1 代码实现 3.3.2 Proxy类讲解 4、动态代理VS静态代理 5、代理模式优缺点 1、什么是代理模式 由于某些原因需要给某对象提供一个代理以控制对…...
Java并发编程基础知识概述
前言 在现代计算机系统和服务器中,多线程并行执行已经成为常态,而且并发编程能够充分利用系统资源,提高程序处理效率和质量。因此,Java并发编程是Java程序员必须掌握的重要技能之一。 线程和进程 在操作系统中,进程是…...
Redis超详细入门手册教程!还不快来看看?
地址: RedisRedis is an open source (BSD licensed), in-memory data structure store, used as a database, cache, and message broker. Redis provides data structures …https://redis.io/ 1:NoSQL简介 1.1:数据库应用的演变历程 单…...
代码随想录算法训练营第四十九天| 121. 买卖股票的最佳时机、122.买卖股票的最佳时机II
文章目录 121. 买卖股票的最佳时机122.买卖股票的最佳时机II 121. 买卖股票的最佳时机 为什么定义dp数组为二维数组? dp数组定义,dp(i)[0] 表示第i天持有股票所得最多现金,dp(i)[1]表示第i天不持有股票的状态(未必当前卖出&#x…...
零基础如何学习挖漏洞?看这篇就够了【网络安全】
前言 有不少阅读过我文章的伙伴都知道,我从事网络安全行业已经好几年,积累了丰富的经验和技能。在这段时间里,我参与了多个实际项目的规划和实施,成功防范了各种网络攻击和漏洞利用,提高了安全防护水平。 也有很多小…...
Twitter 推荐算法底有多牛? 已斩获11.7K star
点击上方“Github中文社区”,关注 看Github,每天提升第070期分享 ,作者:Huber | Github中文社区 大家好,我是Huber。 在美国当地时间 3 月 31 日,马斯克履行当初的诺言,他宣布了 Twitter 算法的…...
看过这篇文章,读懂数据分析
一、为什么需要数据分析 数据分析的重要性不言而喻,没有数据,就是感性。数据不会被观点打败,数据只能被数据打败。我们现在妥妥地已经进入了数据时代。 量化IT投资成效,以数据驱动决策 站在公司或者决策者角度,数据最…...
[计算机图形学]光场,颜色与感知(前瞻预习/复习回顾)
一、Light Field / Lumigraph—光场 1.我们看到的是什么 我们的眼睛能够把3D世界转换为2D的成像信号被我们感知,如上面第一幅图,这就是我们看到整个世界的过程,那么如果我们把之前记录的光的信息都完美的放在一个幕布上,那么我们…...
L4公司进军辅助驾驶,放话无图也能跑遍中国
作者 | Amy 编辑 | 德新 高阶智能驾驶走向规模量产,高精地图成为关键的门槛之一。今年,多家车企和智驾公司都喊出「不依赖高精地图,快速大规模落地」的口号。 华为、小鹏、元戎以及毫末等,可能是最快在国内量产 无高精图智…...
【Java笔试强训 17】
🎉🎉🎉点进来你就是我的人了博主主页:🙈🙈🙈戳一戳,欢迎大佬指点! 欢迎志同道合的朋友一起加油喔🤺🤺🤺 目录 一、选择题 二、编程题 🔥杨辉三角…...
【IPv6】基本概念及字段
IPV4知识点: 字段值 IPv4字段共 字段值解释Version版本版本字段,可以区分V4和V6版本,V4是0100,V6是0110,需要注意的是V4和V6头部除了版本字段位置相同外,其他都是不一样的,因此两个协议不能直…...
数据库中的 Schema 变更实现
线上沙龙-技术流第 30 期营业啦 05月09日(周二)19:30 KaiwuDB - B站直播间 传统数据库操作 Schema 变更时,第一步便是锁表,需持续到 Schema 变更操作完成。这样的做法虽然实现简单,无需考虑事务并发带来的影响&#…...
【C++ 学习 ②】- 类和对象(上)
目录 一、 面向对象的基本理念 1.1 - 什么是对象? 1.2 - 类和对象 1.3 - 面向对象的五条原则 1.4 - 面向过程 vs 面向对象 二、C 中的结构体 三、类的定义 3.1 - 类的两种定义方式 3.2 - 成员变量的命名规范 四、类的访问限定符和封装 4.1 - 访问限定符 …...
最好的物联网教程:软硬结合——从零打造物联网
在大学里不同专业有着不同的追求:机械类与强电类专业学生追求的是 “机电合一” ,既懂机械又懂电气,整个电气机械自动化便能打通。弱电类专业学生追求的是 “软硬结合” ,既懂硬件又懂软件,整个电子产品便能打通。我作…...
猫狗训练集训练报错:Failed to find data adapter that can handle input
这里写自定义目录标题 Jupyter Notebook6.5.4 tensorflow 2.12.0 pillow 9.5.0 numpy 1.23.5 keras 2.12.0 报错详细内容: ValueError: Failed to find data adapter that can handle input: (<class ‘tuple’> containing values of types {“<class ‘k…...
中国网络安全人才需求
如果你是一个想要入门网络安全行业的小白、如果你是网络安全专业在读的大学生、如果你是正在找工作的新手,那么这篇文章你一定要仔细看。毕竟知己知彼百战百胜,知道行业的人才需求才能更好得发挥自己的优势。 当你打开BOSS直聘、拉钩等招聘网站…...
设计模式之组合模式
目录 1、组合模式的定义 2、组合模式例子 3、组合模式实现 3.1 组合模式的结构 3.2 组合模式的分类 3.3 组合模式代码实现(透明组合模式) 4、组合模式的优点 5、组合模式使用场景 1、组合模式的定义 组合模式又名部分整体模式,是用于把…...
计算机基础书籍
一操作系统 二常见问题总结 1.操作系统的特征? 并发、共享、虚拟、异步性 2.进程阻塞与唤醒的条件 等待 I/O 操作完成请求系统资源失败等待信号量或事件等待子进程结束被高优先级进程抢占 3.如何避免死锁? 1、避免资源竞争 2、破坏循环等待条件 3、优…...
保龄球游戏的获胜者、找出叠涂元素----2023/4/30
保龄球游戏的获胜者----2023/4/30 给你两个下标从 0 开始的整数数组 player1 和 player2 ,分别表示玩家 1 和玩家 2 击中的瓶数。 保龄球比赛由 n 轮组成,每轮的瓶数恰好为 10 。 假设玩家在第 i 轮中击中 xi 个瓶子。玩家第 i 轮的价值为: …...
jQuery事件
1. jQuery事件注册 单个事件注册 语法: element.事件(function(){}) eg:$(“div”).click(function(){ 事件处理程序 }) 其他事件和原生基本一致。比如mouseover、mouseout、blur、focus、change、keydown、keyup、resize、scroll 等 <!DOCTYP…...
初识SpringCloud
一、软件架构演进 单体架构 垂直架构 分布式架构 SOA架构 微服务架构 二、微服务架构 2.1 微服务理念 "微服务”一词源 于 Martin Fowler的名为 Microservices的博文,可以在他的官方博客上找到http://martinfowler.com/articles/microservices.html微服务是系统架构上…...
安装java配置
目录 安装JDK 编辑 环境变量配置 3、检验环境变量配置 二、安装tomcat 验证Tomcat配置是否成功 三、安装Mysql 一、安装 二、卸载 四、安装Maven 安装JDK 点击更改将C直接给为F即可。 点击确定后进行安装,安装完以后会提示安装JRE; 检测是否已经安装JDK的…...
KBO的选秀会有哪些规定和流程`棒球7号位
KBO(韩国职业棒球联盟)的选秀会有以下规定和流程: 1. 选秀对象:KBO的选秀会主要面向年满18岁及以上的高中和大学生,以及海外球员和自由球员。KBO的球队可以在选秀会中挑选所需的球员,每个球队有一定数量的选…...
男子订民宿被毁约5个家庭漂泊街头 房东:住满了,没办法
据媒体报道,5月1日,一位叫做诸先生的消费者和朋友们提前在平台上预订了五一假期前往青岛金沙滩地中海两天的别墅民宿,并支付了房款9600元。 但是当他们到达目的地前一个半小时联系房东时,却发现联系不上人。到达指定地点后&#x…...
Vue快速入门,常用指令,生命周期
Vue常用指令 案例: <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><meta http-equiv"X-UA-Compatible" content"IEedge"><meta name"viewport" content"…...
【热门框架】Mybatis-Plus入门介绍看这一篇文章就足够了
MyBatis-Plus 是在 MyBatis 的基础上进行了封装,提供了更加便捷的开发方式,具有简化开发、提高效率等优点。以下是 MyBatis-Plus 的一些特点和用法: 通用 CRUD 操作:MyBatis-Plus 提供了通用的 CRUD 接口,可以直接调用…...
Node【Node.js 20】新特性
文章目录 🌟前言🌟Node.js 20: 一次重要的升级和改进🌟Internationalization API Update🌟端口管理器🌟字符串处理🌟 更好的调试工具🌟 Crypto模块的更新🌟总结🌟写在最后…...
前端程序员的职业发展规划与路线——ChatGPT的回答
文章目录 一、前端程序员的职业规划是?回答1: 作为一个前端开发程序员,您的职业发展路线可能如下:回答2:作为前端开发程序员,您的职业发展路线可能如下:回答3: 你的职业发展路线可能…...
AlgoC++第八课:手写BP
目录 手写BP前言1. 数据加载2. 前向传播3. 反向传播总结 手写BP 前言 手写AI推出的全新面向AI算法的C课程 Algo C,链接。记录下个人学习笔记,仅供自己参考。 本次课程主要是手写 BP 代码 课程大纲可看下面的思维导图 1. 数据加载 我们首先来实现下MNIST…...
【Java笔试强训 27】
🎉🎉🎉点进来你就是我的人了博主主页:🙈🙈🙈戳一戳,欢迎大佬指点! 欢迎志同道合的朋友一起加油喔🤺🤺🤺 目录 一、选择题 二、编程题 🔥 不用加…...
个人网站备案材料填写/广州竞价托管代运营
一、变量初始化以及默认值设置1.$var与${var}:这两种写法本质上是一样的,但$var有时候会产生混淆,而${var}一般不会,可以把变量和字符串组合起来使用,比如name${first}-on-${last}2.${var-default}与${var:-default}&a…...
梦扬科技 合肥网站建设/google搜索免费入口
介绍 张量处理单元( Tensor Processing Unit, TPU ) 是谷歌专门为神经网络机器学习开发的人工智能加速器 专用集成电路(ASIC) ,特别是使用谷歌自己的TensorFlow软件。谷歌于 2015 年开始在内部使用 TPU,并于 2018 年将它们作为其云基础设施的一部分并通过提供较小版本的芯片出…...
中国工商做年报网站/搜索引擎网站优化推广
触发器 我们使用MySQL的过程中可能会有下边这些需求: 在向t1表插入或更新数据之前对自动对数据进行校验,要求m1列的值必须在1~10之间,校验规则如下: 如果插入的记录的m1列的值小于1,则按1插入。如果m1列的值大于10&am…...
网站没有设置关键词/营销网站都有哪些
在模拟和数字PCB设计中,旁路或去耦电容(0.1uF)应尽量靠近器件放置。供电电源去耦电容(10uF)应放置在电路板的电源线入口处。所有情况下,这些电容的引脚都应较短。 在模拟布线设计中,旁路电容通常用于旁路电源上的高频信号,如果不加…...
外贸网站建设推广优化/国内seo公司
背景 首先我是个菜鸡,工资也低的一笔。 刚毕业时候在一家国企上班干 app 开发,干了快两年的时候,跳槽到了一家伪大厂干安全。投了不少简历都没有回音,只有这加伪大厂要我就来了。当时说好了会接触一些底层的东西,然而…...
重庆商城网站制作报价/网络营销的用户创造价值
目录 docker 安装ElasticSEarch亲测步骤 1:docker search ElasticSearch 2: docker pull elasticsearch:5.1.1 3:下载好后,查看镜像:docker images 4:创建实例启动: 5:查看服务:docker ps 6:…...