【结构型模式-代理模式】

概述

由于某些原因需要给某对象提供一个代理以控制该对象的访问。这时,访问对象不适合或者不能直接引用目标对象,代理对象作为访问对象与目标对象之间的中介。
Java中的代理按照代理类生成时机不同又分为静态代理和动态代理。静态代理代理类在编译期就生成,而动态代理类则是在Java运行时动态生成。动态代理又有JDK代理和CGLib代理两种。

结构

代理(Proxy)模式分为三种角色:

  • 抽象主题(Subject)类:通过接口或抽象类声明真实主题和代理对象实现的业务方法。
  • 真实主题(Real Subject)类:实现了抽象主题中的具体业务,是代理对象所代表的真实对象,是最终要引用的对象。
  • 代理(Proxy)类:提供了与真实主题相同的接口,其内部含有对真实主题的引用,它可以访问、控制或拓展真实主题的功能。
    在这里插入图片描述
静态代理
package com.syn.proxy.static_proxy;/*卖票规范*/
public interface SellTickets {void sell();
}
package com.syn.proxy.static_proxy;/*火车站卖票*/
public class TrainStation implements  SellTickets{@Overridepublic void sell() {System.out.println("火车站卖票.");}
}
package com.syn.proxy.static_proxy;/*代理点*/
public class Proxypoint implements SellTickets{private TrainStation trainStation = new TrainStation();@Overridepublic void sell() {System.out.println("代理收取费用.");trainStation.sell();}
}
package com.syn.proxy.static_proxy;/*客户端买票*/
public class Client {public static void main(String[] args) {/*创建代理类*/Proxypoint proxypoint = new Proxypoint();/*买票*/proxypoint.sell();}
}

在这里插入图片描述

JDK动态代理
package com.syn.proxy.jdk_proxy;/*卖票规范*/
public interface SellTickets {void sell();
}
package com.syn.proxy.jdk_proxy;/*火车站卖票*/
public class TrainStation implements SellTickets {@Overridepublic void sell() {System.out.println("火车站卖票.");}
}
package com.syn.proxy.jdk_proxy;import com.syn.proxy.static_proxy.SellTickets;
import com.syn.proxy.static_proxy.TrainStation;import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;/*获取代理对象的工厂类*/
public class ProxyFactory {/*声明目标对象*/private TrainStation trainStation = new TrainStation();public SellTickets getProxyObject(){/*返回代理对象*/SellTickets proxyObject  =  (SellTickets) Proxy.newProxyInstance(/*用于加载代理类,可以通过目标对象获取类加载器*/trainStation.getClass().getClassLoader(),/*代理类实现的接口字节码对象*/trainStation.getClass().getInterfaces(),/*代理对象的调用处理程序*/new InvocationHandler() {@Overridepublic Object invoke(Object proxy, Method method, Object[] args) throws Throwable {System.out.println("代理收费(JDK动态版本).");/*执行目标对象方法*/Object object = method.invoke(trainStation,args);return object;}});return proxyObject;}
}
package com.syn.proxy.jdk_proxy;import com.syn.proxy.static_proxy.SellTickets;public class Client {public static void main(String[] args) {/*创建代理工厂*/ProxyFactory proxyFactory = new ProxyFactory();/*使用工厂获取代理对象*/SellTickets proxyObject = proxyFactory.getProxyObject();/*调用目标方法*/proxyObject.sell();}
}

在这里插入图片描述

CDLIB动态代理

对于上面的案例,如果没有定义SellTickets接口,只定义了TrainStation。很显然JDK动态代理便无法使用了,因为JDK动态代理要求必须定义接口,对接口进行代理。
CGLIB是一个功能强大,高性能的代码生成包,它为没有实现接口的类提供代理,为JDK的动态代理提供了很好的补充。
需要引入maven包

    <dependencies><dependency><groupId>cglib</groupId><artifactId>cglib</artifactId><version>3.1</version></dependency></dependencies>
package com.syn.proxy.cglib_proxy;/*火车站卖票*/
public class TrainStation{public void sell() {System.out.println("火车站卖票.");}
}
package com.syn.proxy.cglib_proxy;import net.sf.cglib.proxy.Enhancer;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;import java.lang.reflect.Method;/*代理对象工厂*/
public class ProxyFactory implements MethodInterceptor {/*声明火车站对象*/private TrainStation trainStation = new TrainStation();public TrainStation getProxyObject(){/*创建Enhancer对象,类似于JDK代理中的Proxy类*/Enhancer enhancer = new Enhancer();/*设置父类的字节码对象*/enhancer.setSuperclass(TrainStation.class);/*设置回调函数*/enhancer.setCallback(this);/*创建代理对象*/return (TrainStation) enhancer.create();}@Overridepublic Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {System.out.println("代理收费(CGLIB动态版本).");/*要调用目标对象的方法*/return method.invoke(trainStation,objects);}
}
package com.syn.proxy.cglib_proxy;public class Client {public static void main(String[] args) {/*创建代理工厂对象*/ProxyFactory proxyFactory = new ProxyFactory();/*获取代理对象*/TrainStation proxyObject = proxyFactory.getProxyObject();/*调用代理对象的sell方法卖票*/proxyObject.sell();}
}

在这里插入图片描述

三种代理对比

  • jdk代理和CGLIB代理

使用CGLib实现动态代理,CGLib底层采用ASM字节码生成框架,使用字节码技术生成代理类,在JDK1.6之前比使用Java反射效率要高。唯一需要注意的是,CGLib不能对声明为final的类或者方法进行代理,因为CGLib原理是动态生成被代理类的子类。
在JDK1.6、JDK1.7、JDK1.8逐步对JDK动态代理优化之后,在调用次数较少的情况下,JDK代理效率高于CGLib代理效率,只有当进行大量调用的时候,JDK1.6和JDK1.7比CGLib代理效率低一点,但是到JDK1.8的时候,JDK代理效率高于CGLib代理。所以如果有接口使用JDK动态代理,如果没有接口使用CGLIB代理。

  • 动态代理和静态代理

动态代理与静态代理相比较,最大的好处是接口中声明的所有方法都被转移到调用处理器一个集中的方法中处理(InvocationHandler.invoke)。这样,在接口方法数量比较多的时候,我们可以进行灵活处理,而不需要像静态代理那样每一个方法进行中转。
如果接口增加一个方法,静态代理模式除了所有实现类需要实现这个方法外,所有代理类也需要实现此方法。增加了代码维护的复杂度。而动态代理不会出现该问题。

优缺点

优点:

  • 代理模式在客户端与目标对象之间起到一个中介作用和保护目标对象的作用;
  • 代理对象可以扩展目标对象的功能;
  • 代理模式能将客户端与目标对象分离,在一定程度上降低了系统的耦合度。

缺点:

  • 增加了系统的复杂度。

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

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

相关文章

情感分析新纪元:Transformer模型的革命性应用

情感分析新纪元&#xff1a;Transformer模型的革命性应用 情感分析&#xff0c;又称为意见挖掘&#xff0c;是自然语言处理&#xff08;NLP&#xff09;领域中的一项重要任务&#xff0c;它旨在从文本数据中识别和提取主观信息&#xff0c;判断文本所表达的情感倾向&#xff0…

MACOS查看硬盘读写量

一、安装Homebrew 按照提示进行安装 /bin/zsh -c "$(curl -fsSL https://gitee.com/cunkai/HomebrewCN/raw/master/Homebrew.sh)"二、安装smartmontools brew install smartmontools三、查看硬盘读写量等信息 sudo smartctl -a /dev/disk0

WPF 制作一个文字漂浮提示框

WPF好像没有自带的文字提示漂浮&#xff0c;我们可以定制一个。 效果如下&#xff1a; xaml xaml如下&#xff1a; <Window x:Class"GroupServer.MsgTip"xmlns"http://schemas.microsoft.com/winfx/2006/xaml/presentation"xmlns:x"http://sc…

谷粒商城学习笔记-23-分布式组件-SpringCloud Alibaba-Nacos配置中心-简单示例

之前已经学习了使用Nacos作为注册中心&#xff0c;这一节学习Nacos另外一个核心功能&#xff1a;配置中心。 一&#xff0c;Nacos配置中心简介 Nacos是一个易于使用的平台&#xff0c;用于动态服务发现和配置管理。作为配置中心&#xff0c;Nacos提供了以下核心功能和优势&am…

微软推出全新的学习网站 Microsoft Learn

微软官方宣布推出全新的学习网站 Microsoft Learn&#xff0c;供开发人员学习 Microsoft 技术。 该网站包含所有 Microsoft 产品和服务(从 HoloLens 到 Azure)的技术文档。提供了超过 80 小时的学习内容&#xff0c;涉及 Azure、Dynamics 365、PowerApps、Microsoft Flow 和 Po…

VSTO插件功能介绍-清除空行【进化过程】

大家看到的是完成的成果&#xff0c; 可能不知在其中&#xff0c;写码人的艰辛 今天的主要是记录【进化过程】 用于自勉&#xff0c;与大家共勉&#xff0c;努力 文章中的代码你可复制使用哦 想要的效果若用户选择了区域&#xff0c;选择确定Button对此区域&#xff0c;进行清除…

代码随想录算法训练营Day64|拓扑排序(卡码网117)、dijkstra朴素版

拓扑排序 117. 软件构建 (kamacoder.com) 拓扑排序简单的说是将一个有向图转为线性的排序。 它将图中的所有结点排序成一个线性序列&#xff0c;使得对于任何的边uv&#xff0c;结点u在序列中都出现在结点v之前&#xff0c;这样的序列满足图中所有的前驱-后继关系。 拓扑排…

vue 插槽 【slot】

文章目录 默认插槽具名插槽作用域插槽 默认插槽 父组件中&#xff1a;<Category title"今日热门游戏"><ul><li v-for"g in games" :key"g.id">{{ g.name }}</li></ul></Category> 子组件中&#xff1a;<…

9. 机器人数目

题目描述 本题为填空题&#xff0c;只需要算出结果后&#xff0c;在代码中使用输出语句将所填结果输出即可。 少年宫新近邮购了小机器人配件&#xff0c;共有3类。 &#x1d434;A 类含有&#xff1a;88 个轮子&#xff0c;11 个传感器&#xff1b; &#x1d435;B 类含有:…

深入理解基本数据结构:栈详解

引言 在计算机科学中&#xff0c;数据结构是存储、组织和管理数据的方式。栈是一种重要的线性数据结构&#xff0c;广泛应用于各种编程场景。在这篇博客中&#xff0c;我们将详细探讨栈的定义、特点、操作及其在不同编程语言中的实现。 什么是栈&#xff1f; **栈&#xff08…

java动态代理的使用和代码示例

文章目录 1. 简介2. 代码3. 参考链接 1. 简介 代理类在程序运行时创建的代理方式被成为动态代理。在静态代理中&#xff0c;代理类&#xff08;RenterProxy&#xff09;是自己已经定义好了的&#xff0c;在程序运行之前就已经编译完成。而动态代理是在运行时根据我们在Java代码…

前端vue 实现取色板 的选择

大概就是这样的 一般的web端框架 都有自带的 的 比如 ant-design t-design 等 前端框架 都是带有这个的 如果遇到没有的我们可以自己尝试开发一下 简单 的 肯定比不上人家的 但是能用 能看 说的过去 我直接上代码了 其实这个取色板 就是一个input type 是color 的input …

CTF学习记录(一)——Web基础

目录 Web基础Web基础常用工具ncat(网络工具中的瑞士军刀&#xff0c;功能齐全)curl(一个工作在命令行的发起HTTP请求的工具)BurpSuite(Web核心抓包工具)Hackbar插件SwitchyOmega 代理插件&#xff08;非常牛逼&#xff09;Wappalyzer 技术判断插件EditThisCookie 插件Postman 接…

深入理解Spring Boot中的定时任务调度

深入理解Spring Boot中的定时任务调度 大家好&#xff0c;我是微赚淘客系统3.0的小编&#xff0c;也是冬天不穿秋裤&#xff0c;天冷也要风度的程序猿&#xff01; 1. Spring Boot中的定时任务概述 在现代应用程序开发中&#xff0c;定时任务调度是一项非常常见和重要的功能…

【计算机网络03】不花钱怎么搭建一个网络实验室

使用GNS3和虚拟机搭建网络实验室 1、安装抓包工具分析数据包2、定义和使用抓包筛选器3、安装和配置GNS34、配置路由器和VPCS5、使用WireShark捕获GNS3网络数据包6、VMware创建虚拟机7、使用思科PacketTracer 1、安装抓包工具分析数据包 官网安装wireshark&#xff1a;https://…

python怎么判断字符串以什么结尾

在python编辑器中新建一个data.py。 写上自己的注释。 然后新建一个变量testname。 利用endswith来判断字符串是不是以“ar”结尾。 将结果打印出来。 选择“run”->“run”。 运行该程序&#xff0c;如果是&#xff0c;就会返回true。

JavaScript-日期对象

日期对象 作用&#xff1a;用来表示时间的对象 获取当前时间 const datenew Date();console.log(date);可以得到日期对象&#xff0c;里面的属性有星期&#xff0c;年月日&#xff0c;时分秒 获取指定时间 const datenew Date(2023-05-01);console.log(date); 获取时间戳 时间…

PyTorch深度学习实战(45)——强化学习

PyTorch深度学习实战&#xff08;45&#xff09;——强化学习 0. 前言1. 强化学习基础1.1 基本概念1.2 马尔科夫决策过程1.3 目标函数1.4 智能体学习过程 2. 计算状态值3. 计算状态-动作值4. Q 学习4.1 Q 值4.2 Gym环境4.3 构建 Q 表4.4 探索-利用策略 小结系列链接 0. 前言 强…

悠律凝声环开放式耳机体验:强劲低音、高颜值设计

最近发现了一款潮酷的开放式耳机&#xff0c;不仅颜值抗打&#xff0c;更重要的是能在嘈杂的环境中提供给我一份宁静的沉浸式音乐体验&#xff0c;号称是开放音频中的重低音之王&#xff0c;它就是悠律凝声环开放式耳机。 这款耳机无论其外观设计、音质效果、性价比以及续航能力…

通勤数据:Comma2k19 数据集

A Commute in Data: The comma2k19 Dataset 通勤数据&#xff1a;Comma2k19 数据集 https://arxiv.org/pdf/1812.05752v1 Abstract— comma.ai presents comma2k19, a dataset of over 33 hours of commute in California’s 280 highway. This means 2019 segments, 1 minut…