Java设计模式【代理模式】

news/发布时间2024/5/16 7:42:48

一、前言

1.1 背景

在不改变原有代码的基础上,对方法进行功能性的增强;

1.2 简介

代理模式是一种结构型模式,为其他对象提供一种代理以控制对这个对象的访问。在某些情况下,一个对象不想或者不能直接引用另一个对象,而代理对象可以在客户端和目标对象之间起到中介的作用。

组成

  • 抽象主体(Subject):通过接口或抽象类声明真实主体实现的业务方法
  • 代理(Proxy):实现抽象主体,是真实主体的代理,通过真实主体的业务逻辑方法来实现抽象方法,并可以附加自己的操作
  • 真实主体(RealSubject):实现抽象主体,定义真实主体所要实现的业务逻辑,供代理主体调用

优点

  • 职责清晰
  • 中介的作用、保护目标对象的作用
  • 高扩展性

二、三种实现

  • 静态代理
  • JDK动态代理
  • Cglib动态代理

此处以代驾举例:抽象主体(Driver),代理(ProxyDriver),真实主体(RealDriver)

2.1 静态代理

缺点

  • 代理类过多:代理对象需要和目标对象实现相同的接口或父类
  • 难以维护:一旦接口中增加了方法后,目标对象和代理对象都需要维护
package com.qiangesoft.design.structural.proxy;/*** 静态代理*/
public class StaticProxy {public static void main(String[] args) {RealDriver realDriver = new RealDriver();Driver driver = new ProxyDriver(realDriver);driver.drive("奥迪A6L");}
}/*** 驾驶员接口*/
interface Driver {void drive(String car);
}/*** 真实驾驶员*/
class RealDriver implements Driver {@Overridepublic void drive(String car) {System.out.println("【" + car + "】被开回家了");}
}/*** 代理驾驶员*/
class ProxyDriver implements Driver {private RealDriver realDriver;public ProxyDriver(RealDriver realDriver) {this.realDriver = realDriver;}@Overridepublic void drive(String car) {System.out.println("代驾取钥匙");realDriver.drive(car);System.out.println("代驾还钥匙");}
}

2.2 JDK动态代理

特点

  • 利用JDK的API动态的在内存中构建代理对象(需指定目标对象实现接口的类型、代理对象)
  • 目标对象一定要实现接口,否则不能用动态代理
package com.qiangesoft.design.structural.proxy.jdk;import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;/*** jdk动态代理*/
public class JdkDynamicProxy {public static void main(String[] args) {RealDriver realDriver = new RealDriver();ProxyDriver proxyDriver = new ProxyDriver(realDriver);Driver proxy = (Driver) proxyDriver.getProxyInstance();// 使用代理对象来调用抽象方法proxy.drive("奥迪A6L");}
}/*** 驾驶员接口*/
interface Driver {void drive(String car);
}/*** 真实驾驶员*/
class RealDriver implements Driver {@Overridepublic void drive(String car) {System.out.println("【" + car + "】被开回家了");}
}/*** 代理驾驶员*/
class ProxyDriver implements InvocationHandler {private Object realDriver;public ProxyDriver(RealDriver realDriver) {this.realDriver = realDriver;}public Object getProxyInstance() {// 使用Proxy类的静态方法newProxyInstance来动态地创建一个代理对象,传入真实主题对象的类加载器、接口和处理器return Proxy.newProxyInstance(realDriver.getClass().getClassLoader(), realDriver.getClass().getInterfaces(), this);}@Overridepublic Object invoke(Object proxy, Method method, Object[] args) throws Throwable {System.out.println("代驾取钥匙");Object result = method.invoke(realDriver, args);System.out.println("代驾还钥匙");return result;}
}

2.3 Cglib动态代理

特点

  • 通过生成目标对象的子类实现代理
  • 需要引入cglib的jar包
  • 目标对象的类不能是final(类不能被继承)
  • 目标对象的方法如果有final(方法不能被重写)/static(非对象的方法)修饰,不会被执行。

引入依赖

<dependency><groupId>cglib</groupId><artifactId>cglib</artifactId><version>3.3.0</version>
</dependency>

代码实现

package com.qiangesoft.design.structural.proxy.cglib;import net.sf.cglib.proxy.Enhancer;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;import java.lang.reflect.Method;/*** cglib动态代理*/
public class CglibDynamicProxy {public static void main(String[] args) {RealDriver realDriver = new RealDriver();ProxyDriver proxyDriver = new ProxyDriver(realDriver);RealDriver proxy = (RealDriver) proxyDriver.getProxyInstance();proxy.drive("奥迪A6L");}
}/*** 驾驶员接口*/
interface Driver {void drive(String car);
}/*** 真实驾驶员*/
class RealDriver implements Driver {@Overridepublic void drive(String car) {System.out.println("【" + car + "】被开回家了");}
}/*** 代理驾驶员*/
class ProxyDriver implements MethodInterceptor {private Object realDriver;public ProxyDriver(Object realDriver) {this.realDriver = realDriver;}public Object getProxyInstance() {// 1.工具类Enhancer enhancer = new Enhancer();// 2.设置父类enhancer.setSuperclass(realDriver.getClass());// 3.设置回调函数enhancer.setCallback(this);// 4.创建子类(代理对象)return enhancer.create();}@Overridepublic Object intercept(Object o, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {System.out.println("代驾取钥匙");Object result = method.invoke(realDriver, args);System.out.println("代驾还钥匙");return result;}
}

三、总结

  • 如果加入容器的目标对象有实现接口,用JDK代理
  • 如果目标对象没有实现接口,用Cglib代理
  • 如果目标对象实现了接口,且强制使用cglib代理,则会使用cglib代理。

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

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

相关文章

音频声波的主观感受

一、响度 声压是“客观”的&#xff0c;响度是“主观”的。 响度又称音量。人耳感受到的声音强弱&#xff0c;它是人对声音大小的一个主观感觉量。响度的大小决定于声音接收处的波幅&#xff0c;就同一声源来说&#xff0c;波幅传播的愈远&#xff0c;响度愈小…

【刷题】牛客 JZ64 求1+2+3+...+n

刷题 题目描述思路一 &#xff08;暴力递归版&#xff09;思路二 &#xff08;妙用内存版&#xff09;思路三 &#xff08;快速乘法版&#xff09;思路四 &#xff08;构造巧解版&#xff09;Thanks♪(&#xff65;ω&#xff65;)&#xff89;谢谢阅读&#xff01;&#xff01…

[C#]winform基于opencvsharp结合pairlie算法实现低光图像增强黑暗图片变亮变清晰

【低光图像增强介绍】 在图像处理领域&#xff0c;低光图像增强是一个具有挑战性的任务。由于光线不足&#xff0c;这些图像往往呈现出低对比度、高噪声和细节丢失等问题&#xff0c;严重影响了图像的视觉效果和后续分析的准确性。因此&#xff0c;开发有效的低光图像增强方法…

unity学习(38)——创建(create)角色脚本(panel)--EventSystem

1.在scripts文件夹下创建一个脚本CreatePlayerPanel.cs&#xff0c;脚本挂到panel上&#xff01;给panel加个tag&#xff0c;叫createPanel&#xff0c;脚本内容如下&#xff1a; using System.Collections; using System.Collections.Generic; using TMPro; using UnityEngin…

基于PID-bang-bang控制算法的卫星姿态控制matlab仿真

目录 1.课题概述 2.系统仿真结果 3.核心程序与模型 4.系统原理简介 5.完整工程文件 1.课题概述 基于PID-bang-bang控制算法的卫星姿态控制。仿真输出控制器的控制收敛曲线&#xff0c;卫星姿态调整过程的动画。 2.系统仿真结果 3.核心程序与模型 版本&#xff1a;MATLAB…

浏览器显示「SSL 证书无效」应该如何解决?

作为保护网站传输数据安全的重要工具&#xff0c;SSL证书经常被部署于网站服务器上以实现HTTPS加密。但部分网站部署SSL证书后&#xff0c;访问时有时候会出现SSL 证书无效警示。那么SSL证书无效怎么办&#xff1f;导致SSL证书无效的情况可能是SSL证书本身的原因&#xff0c;也…

HEVC视频编解码标准学习笔记-1

视频编解码标准H.265/HEVC&#xff08;High Efficiency Video Coding&#xff09;通过将视频数据编码为更高效格式&#xff0c;大幅改善了视频流的压缩效率。这里主要介绍Tile、Slice和CTU的定义&#xff0c;以及介绍这些技术组件之间的相互关系。 CTU&#xff08;编码树单元&…

【知识整理】Git Commit Message 规范

一. 概述 前面咱们整理过 Code Review 一文&#xff0c;提到了 Review 的重要性&#xff0c;已经同过gitlab进行CodeReview 的方式&#xff0c;那么本文详细说明一下对CodeReivew非常重要的Git Commit Message 规范。 我们在每次提交代码时&#xff0c;都需要编写 Commit Mes…

力扣226 翻转二叉树 Java版本

文章目录 题目描述解题思路代码 题目描述 给你一棵二叉树的根节点 root &#xff0c;翻转这棵二叉树&#xff0c;并返回其根节点。 示例 1&#xff1a; 输入&#xff1a;root [4,2,7,1,3,6,9] 输出&#xff1a;[4,7,2,9,6,3,1] 示例 2&#xff1a; 输入&#xff1a;root…

笔记-电感充放电过程状态记录

描述&#xff1a;电感充放电过程状态记录 为加深对电感充放电的理解&#xff0c;特做一次记录。 目录 一、准备工作二、电感状态记录1、电感刚开始充电瞬间2、电感充电期间3、电感充电完毕4、电感开始放电瞬间5、电感放电完毕6、电感充放电完整记录 一、准备工作 1、在线平台…

vue2+element医院安全(不良)事件报告管理系统源代码

目录 安全不良事件类型 源码技术栈 医院安全&#xff08;不良&#xff09;事件报告管理系统采用无责的、自愿的填报不良事件方式&#xff0c;有效地减轻医护人员的思想压力&#xff0c;实现以事件为主要对象&#xff0c;可以自动、及时、实际地反应医院的安全、不良、近失事件…

第十一天-Excel的操作

目录 1.xlrd-Excel的读模块 安装 使用 获取工作簿 读取工作簿的内容 xlsxwriter-Excel的写模块 安装 使用 生成图表 add_series参数 图表的样式 demo&#xff1a;生成图表 Excel的操作在python中有多个模块&#xff0c;为了能够快速使用&#xff0c;选择了相对简单…

Sora领航AIGC时代:深度解读行业变革与AI工具全景图

随着人工智能技术的飞速发展&#xff0c;越来越多的企业和行业开始将AI融入其核心业务流程中。在这个背景下&#xff0c;Sora以其独特的视角和全面的解决方案&#xff0c;正引领着AIGC&#xff08;人工智能生成内容&#xff09;的趋势变革。 本文将对Sora进行深度解读&#xf…

vue3在router跳转路由时,params失效问题

vue-router重要提示。 解决方案&#xff1a; 1. 使用query传参 但是变量会直接暴露在url中 2.用store或localStorage这种办法暂存一下。

使用腾讯云COS提示CORS策略阻止的解决方案

报错 看到了跨域报错&#xff0c;进行腾讯云配置 1、找到自己的存储桶 2、点击跨域的CORS设置 3、进行规则添加

人工智能_CPU微调ChatGLM大模型_使用P-Tuning v2进行大模型微调_007_微调_002---人工智能工作笔记0102

这里我们先试着训练一下,我们用官方提供的训练数据进行训练. 也没有说使用CPU可以进行微调,但是我们先执行一下试试: https://www.heywhale.com/mw/project/6436d82948f7da1fee2be59e 可以看到说INT4量化级别最低需要7GB显存可以启动微调,但是 并没有说CPU可以进行微调.我们…

SpringBoot实现缓存预热的几种常用方案

&#x1f3f7;️个人主页&#xff1a;牵着猫散步的鼠鼠 &#x1f3f7;️系列专栏&#xff1a;Java全栈-专栏 &#x1f3f7;️个人学习笔记&#xff0c;若有缺误&#xff0c;欢迎评论区指正 前些天发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&…

spring boot3登录开发-3(账密登录逻辑实现)

⛰️个人主页: 蒾酒 &#x1f525;系列专栏&#xff1a;《spring boot实战》 &#x1f30a;山高路远&#xff0c;行路漫漫&#xff0c;终有归途。 目录 前置条件 内容简介 用户登录逻辑实现 创建交互对象 1.创建用户登录DTO 2.创建用户登录VO 创建自定义登录业务异…

Selenium IDE插件录制网页,解放双手

1、 国内下载地址 https://www.crx4chrome.com/crx/77585/ &#xff0c;这个网络正常基本可以下载&#xff0c;目前最新版本是3.17.2。 点击Crx4Chrome下载。下载后的文件名称是&#xff1a;mooikfkahbdckldjjndioackbalphokd-3.17.2-Crx4Chrome.com.crx。 2、 安装 直接打开…

easyui 手风琴Accordion 面板的高度设置

今天接到一个新的小需求&#xff0c;如下图&#xff0c;当预算表单只有一个时&#xff0c;要求不显示预算表单这块的内容。 考虑到页面创建时用到了表单的回调和点击方法&#xff0c;所以不能单纯的移除&#xff0c;移除右侧表格的创建会报错&#xff0c;所以只能隐藏。 隐藏…
推荐文章