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

设计模式--结构型--代理模式

    • 代理模式
      • 概述
      • 结构
      • 静态代理案例:卖车票
      • jdk动态代理
      • cglib代理
      • 三种代理对比
      • 优缺点
      • 使用场景

代理模式

概述

由于某些原因需要给某对象提供一个代理以控制该对象的访问。这时,访问对象不适合或者不能直接引用目标对象,代理对象作为访问对象和目标对象之间的中介。
java中的代理机制分为静态代理和动态代理

  • 静态代理:代理类在在编译期就生成
  • 动态代理:代理类在java运行时动态生成。
    • JDK代理
    • CGLib代理

结构

代理模式分为三种角色:

  • 抽象主题类:通过接口或抽象类声明真实主题和代理对象实现的业务方法。
  • 真实主题类:实现了抽象主题中的具体业务,是代理对象所代表的真实对象,是最终要引用的对象。
  • 代理类:提供了与真实主题相同的接口,其内部含有对真实主题的引用,它可以访问、控制或扩展真实主题的功能。

静态代理案例:卖车票

市面上任何卖火车票软件都是通过12306来买的,这就是一个典型的代理模式,12306是目标对象,其他售票软件是代理对象。
在这里插入图片描述

public class ProxyPoint implements SellTicket{// 声明12306类对象private TrainStation trainStation = new TrainStation();@Overridepublic void sell() {System.out.println("其它app买票---可以增强");trainStation.sell();}
}
/*** 卖火车票的接口*/
public interface SellTicket {void sell();
}
public class TrainStation implements SellTicket{@Overridepublic void sell() {System.out.println("12306卖火车票");}
}
public class Test01 {public static void main(String[] args) {ProxyPoint proxyPoint = new ProxyPoint();proxyPoint.sell();}
}

从上面代码中可以看出测试类是直接访问ProxyPoint类对象,也就是说ProxyPoint作为目标访问对象和目标对象的中介,同时也对sell方法进行了增强。

jdk动态代理

接下来使用动态代理实现上面案例,java中提供了一个动态代理类Proxy,Proxy并不是我们上面说的代理对象类,
而是提供了一个创建代理对象的静态方法(newProxyInstance)来获取代理对象。

/*** 获取代理对象的工厂类* 代理类也实现了对应的接口*/
public class ProxyFactory {// 声明目标对象private TrainStation station = new TrainStation();public SellTicket getProxyObject(){/*** ClassLoader loader 类加载器,用于加载代理类。可以通过目标对象获取类加载器* Class<?>[] interfaces 代理类实现的接口的字节码对象* InvocationHandler h 代理对象的调用处理程序*/SellTicket proxyObject = (SellTicket) Proxy.newProxyInstance(station.getClass().getClassLoader(),station.getClass().getInterfaces(),/*** Object proxy:代理对象,和proxyObject对象是同一个对象* Method method:对接口中的方法进行封装的method对象* Object[] args:调用方法的实际参数* 返回值:方法的返回值*/new InvocationHandler() {@Overridepublic Object invoke(Object proxy, Method method, Object[] args) throws Throwable {//System.out.println("代售app---增强");// 执行目标对象的方法return method.invoke(station, args);}});return proxyObject;}
}
/*** 卖火车票的接口*/
public interface SellTicket {void sell();
}

cglib代理

/*** 代理对象工厂,用来获取代理对象*/
public class ProxyFactory implements MethodInterceptor {private TrainStation station = new TrainStation();public TrainStation getProxyObject(){// 创建Enhancer对象,类似jdk代理中的Proxy类Enhancer enhancer = new Enhancer();// 设置父类的字节码对象enhancer.setSuperclass(TrainStation.class);// 设置回调函数enhancer.setCallback(this);// 创建代理对象TrainStation proxyObject = (TrainStation) enhancer.create();return proxyObject;}@Overridepublic Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {System.out.println("cglib代理");// 要调用目标对象的方法TrainStation invoke = (TrainStation) method.invoke(station, objects);return invoke;}
}
public class TrainStation {public void sell() {System.out.println("12306卖火车票");}
}
public class Test02 {public static void main(String[] args) {// 创建代理工厂对象ProxyFactory factory = new ProxyFactory();// 获取代理对象TrainStation proxyObject = factory.getProxyObject();// 调用代理对象中的sell方法proxyObject.sell();}
}

三种代理对比

  • jdk代理和cglib代理
    • 使用CGLib实现动态代理,cglib底层采用ASM字节码生产框架,使用字节码技术生成代理类,在jdk1.6之前比使用java反射效率要高。
      唯一需要注意的是:cglib不能对声明为final的类或方法进行代理,因为cglib原理是动态生成被代理的子类。

      在jdk1.8对jdk动态代理优化后,jdk代理效率高于cglib代理,如果有接口使用jdk代理,没有接口使用cglib代理。

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

优缺点

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

使用场景

  • 远程代理
    • 本地服务通过网络请求远程服务。为了实现本地到远程的通信,我们需要实现网络通信,处理其中可能的异常。为良好的代码设计和可维护性,
      我们将网络通信部分隐藏起来,只暴露给本地服务一个接口,通过该接口即可访问远程服务提供的功能,而不必过多关心通信部分的细节。
  • 防火墙代理
    • 将浏览器配置成使用代理功能时,防火墙就可以将浏览器的请求转给互联网;当互联网返回响应时,代理服务器再把他转给你的浏览器。
  • 保护代理
    • 控制对一个对象的访问,如果需要,可以给不同的用户提供不同级别的使用权限。

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

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

相关文章

控制理论simulink+matlab

控制理论下的simulink和matlab使用 根轨迹LQR控制器简单使用状态观测器设计 根轨迹 z [-1]; %开环传递函数的零点 p [0 -2 -3 -4]; %开环传递函数的系统极点 k 1; %开环传递函数的系数&#xff0c;反映在比例上 g zpk(z,p,k); %生成开环传递函数%生成的传递函数如…

使用Swift Package Manager (SPM)实现xcframework分发

Swift Package Manager (SPM) 是苹果官方提供的用于管理 Swift 项目的依赖关系和构建过程的工具。它是一个集成在 Swift 编程语言中的包管理器&#xff0c;用于解决在开发过程中管理和构建包依赖项的需求。 Package结构 一个 Package&#xff08;包&#xff09;由 Swift 源码…

Java数据结构-模拟ArrayList集合思想,手写底层源码(1),底层数据结构是数组,编写add添加方法,正序打印和倒叙打印

package com.atguigu.structure; public class Demo02_arrayList {public static void main(String[] args) {MyGenericArrayListV1 arrayListV1 new MyGenericArrayListV1();//arr.add(element:100,index:1);下标越界&#xff0c;无法插入//初始化&#xff08;第一次添加&…

运维知识点-Kubernetes_K8s

Kubernetes RBAC配置不当攻击场景攻击过程 RBAC配置不当 Service Account本质是服务账号&#xff0c;是Pod连接K8s集群的凭证。 在默认情况下&#xff0c;系统会为创建的Pod提供一个默认的Service Account&#xff0c; 用户也可以自定义Service Account&#xff0c;与Service…

警惕Mallox勒索病毒的最新变种mallox,您需要知道的预防和恢复方法。

引言&#xff1a; 在当今数字时代&#xff0c;勒索病毒已经成为网络安全领域的一大威胁&#xff0c;而其中之一的.mallox勒索病毒更是具有高度破坏性。本文将深入介绍.mallox勒索病毒&#xff0c;包括其攻击方式、数据加密特征&#xff0c;以及如何有效恢复被加密的数据文件&a…

SparkSQL的编程模型(DataFrame和DataSet)

1.2 SparkSQL的编程模型(DataFrame和DataSet) 1.2.1 编程模型简介 主要通过两种方式操作SparkSQL&#xff0c;一种就是SQL&#xff0c;另一种为DataFrame和Dataset。 SQL SQL不用多说&#xff0c;就和Hive操作一样&#xff0c;但是需要清楚一点的时候&#xff0c;SQL操作的是…

【科技前沿】数字孪生技术改革智慧供热,换热站3D可视化引领未来

换热站作为供热系统不可或缺的一部分&#xff0c;其能源消耗对城市环保至关重要。在双碳目标下&#xff0c;供热企业可通过搭建智慧供热系统&#xff0c;实现供热方式的低碳、高效、智能化&#xff0c;从而减少碳排放和能源浪费。通过应用物联网、大数据等高新技术&#xff0c;…

数据库操作习题12.12

考虑如下的人员数据&#xff0c;其中加下划线的是主码&#xff0c;数据库模式由四个关系组成: employee (empname, street, city) works (empname, compname, salary) company(id, compname, city) managers (empname, mgrname) 其中 关系 employee 给出人员的基本信息,包括人员…

【hadoop】解决浏览器不能访问Hadoop的50070、8088等端口?!

【hadoop】解决浏览器不能访问Hadoop的50070、8088等端口&#xff1f;&#xff01;&#x1f60e; 前言&#x1f64c;【hadoop】解决浏览器不能访问Hadoop的50070、8088等端口&#xff1f;&#xff01;查看自己的配置文件&#xff1a;最终成功访问如图所示&#xff1a; 总结撒花…

2023年度佳作:AIGC、AGI、GhatGPT 与人工智能大模型的创新与前景展望

&#x1f3ac; 鸽芷咕&#xff1a;个人主页 &#x1f525; 个人专栏:《linux深造日志》《粉丝福利》 ⛺️生活的理想&#xff0c;就是为了理想的生活! ⛳️ 写在前面参与规则 ✅参与方式&#xff1a;关注博主、点赞、收藏、评论&#xff0c;任意评论&#xff08;每人最多评论…

Unity | Shader基础知识(第八集:案例<漫反射材质球>)

目录 一、本节介绍 1 上集回顾 2 本节介绍 二、什么是漫反射材质球 三、 漫反射进化史 1 三种算法结果的区别 2 具体算法 2.1 兰伯特逐顶点算法 a.本小节使用的unity自带结构体。 b.兰伯特逐顶点算法公式 c.代码实现——兰伯特逐顶点算法 2.2 代码实现——兰伯特逐…

基于MLP完成CIFAR-10数据集和UCI wine数据集的分类

基于MLP完成CIFAR-10数据集和UCI wine数据集的分类&#xff0c;使用到了sklearn和tensorflow&#xff0c;并对图片分类进行了数据可视化展示 数据集介绍 UCI wine数据集&#xff1a; http://archive.ics.uci.edu/dataset/109/wine 这些数据是对意大利同一地区种植的葡萄酒进…

Linux调试器gdb的用法

Linux调试器gdb的用法 1. debug/release版本之间的比较2. gdb调试器的基本指令3. 使用展示 1. debug/release版本之间的比较 在之前学习C语言的的时候出过一期vs的调试技巧。 而对于现在的Linux下的调试器gdb其实也是换汤不换药的&#xff0c;基本上的调试思路是不会改变的&am…

http -- 跨域问题详解(浏览器)

参考链接 参考链接 1. 跨域报错示例 Access to XMLHttpRequest at http://127.0.0.1:3000/ from origin http://localhost:3000 has been blocked by CORS policy: Response to preflight request doesnt pass access control check: No Access-Control-Allow-Origin header…

【Java 集合】LinkedBlockingDeque

在开始介绍 LinkedBlockingDeque 之前, 我们先看一下 LinkedBlockingDeque 的类图: 从其中可以看出他直接实现了 BlockingDeque 接口, 而 BlockingDeque 又实现了 BlockingQueue 的接口, 所以它本身具备了队列的特性。 而实现 BlockingDeque 使其在 BlockingQueue 的基础上多了…

Spring Boot自动装配原理以及实践

了解自动装配两个核心 Import注解的作用 Import说Spring框架经常会看到的注解&#xff0c;它有以下几个作用: 导入Configuration类下所有的bean方法中创建的bean。导入import指定的bean&#xff0c;例如Import(AService.class)&#xff0c;就会生成AService的bean&#xff0…

获取请求体中json数据并解析到实体对象

目录 相关依赖 前端代码 后端代码 测试结果 相关依赖 <dependency><groupId>com.alibaba</groupId><artifactId>fastjson</artifactId><version>1.2.83</version> </dependency> <dependency><groupId>comm…

02 ModBus TCP

目录 一、ModBus TCP 一帧数据格式 二、0x01 读线圈状态 三、0x03读保持寄存器 四、0x05写单个线圈 五、0x06 写单个寄存器 六、0x0f写多个线圈 七、0x10&#xff1a;写多个保持寄存器 八、通信过程 九、不同modbus通信模式的应用场景 一、ModBus TCP 一帧数据格式 其…

fill-in-the-middle(FIM) 实现与简单应用

1 背景 传统训练的 GPT 模型只能根据前文内容预测后文内容&#xff0c;但有些应用比如代码生成器&#xff0c;需要我们给出上文和下文&#xff0c;使模型可以预测中间的内容&#xff0c;传统训练的 GPT 就不能完成这类任务。 传统训练的 GPT 只能根据上文预测下文 使用 FIM…

基于Pytest+Requests+Allure实现接口自动化测试

一、整体结构 框架组成&#xff1a;pytestrequestsallure 设计模式&#xff1a; 关键字驱动 项目结构&#xff1a; 工具层&#xff1a;api_keyword/ 参数层&#xff1a;params/ 用例层&#xff1a;case/ 数据驱动&#xff1a;data_driver/ 数据层&#xff1a;data/ 逻…