Java设计模式 _结构型模式_代理模式(静态,动态)

news2024/10/6 1:36:58

一、基础概念

1、代理模式
代理模式(Proxy Pattern)是一种结构型设计模式。它允许我们通过添加一个代理对象来控制对另一个对象的访问,从而实现一些额外的功能,如访问控制、日志记录、性能监控等。代理模式主要分为静态代理和动态代理两种。

2、静态代理
静态代理是指由程序员创建或工具生成代理类的源码,再编译代理类。代理类和委托类在运行前就确定了关系,且这种关系在运行期不能被改变。
优点:
可以在不修改目标对象的前提下,对目标对象的功能进行扩展。
代理类和目标对象实现相同的接口,因此具有相同的方法签名,这使得代理类可以无缝地替换目标对象。
缺点:
如果需要代理的目标类很多,那么就需要编写大量的代理类,这会导致代码冗余和难以维护。
一旦接口增加方法,目标对象与代理对象都需要进行维护。

3、动态代理
动态代理是指在程序运行期间,根据反射等机制动态地生成代理类的源码,并加载到JVM中。动态代理的源码在程序运行期间生成,因此不存在代理类的字节码文件。
优点:
无需手动编写代理类,减少了代码冗余和提高了可维护性。
适用于目标对象接口不确定或需要频繁变更的场景。
可以实现更复杂的代理逻辑,如AOP(面向切面编程)等。
缺点:
由于动态代理是基于反射实现的,因此相对于静态代理来说,性能上可能稍逊一筹。
动态代理只能代理实现了接口的类,不能代理实现了抽象类或继承了具体类的对象。

4、InvocationHandler
InvocationHandler 是一个接口,它是动态代理模式的核心部分。当使用 Proxy 类和 InvocationHandler 接口来创建动态代理时,你实际上是在创建一个实现了指定接口的代理类实例,该实例在方法调用时会转发到 InvocationHandler 的 invoke 方法。

5、静态代理实现思路
(1)、定义规范接口
(2)、编写实现类1,实现上诉规范接口
(3)、编写代理类,实现上诉规范接口,同时将实现类注入为代理类的成员属性,编写构造方法或其他方法实例化这个成员属性。
(4)、编写代理类的实现方法,通过引用成员实现类的相同方法实现,可以在前后进行相关的业务扩展。
(5)、生成代理对象,执行业务方法

6、动态代理实现思路
(1)、定义规范接口
(2)、编写实现类1,实现上诉规范接口
(3)、编写InvocationHandler接口的实现方法,扩展业务需要,如之前过滤数据,之后记录日志等。
(4)、通过Proxy对象和实现的InvocationHandler类创建目标对象的代理对象
(5)、调用代理对象,执行业务方法

二、代码示例

1、静态代码示例

// 1、定义规范接口
public interface CarApply {
    public void useCar(String user,String date);
}
// 2、创建实现类
public class EmployeeCarApply implements CarApply{
    @Override
    public void useCar(String user, String date) {
        System.out.println(user+"在"+date+"申请用车");
    }
}
// 3、创建代理类
public class ProxyCarApply implements CarApply {

    private CarApply carApply;

    public ProxyCarApply(CarApply carApply) {
        this.carApply = carApply;
    }

    @Override
    public void useCar(String user, String date) {
        if (user.contains("经理")) {
            System.out.println(date + "给" + user + "安排一名司机");
        }
        carApply.useCar(user, date);
        if (user.contains("经理")) {
            System.out.println("2个小时后给" + user + "订餐");
        }
    }
}
// 测试
public static void main(String[] args) {
        EmployeeCarApply employeeCarApply1 = new EmployeeCarApply();
        employeeCarApply1.useCar("李四经理","2024年3月15日");
        System.out.println();

        ProxyCarApply proxyCarApply = new ProxyCarApply(new EmployeeCarApply());
        proxyCarApply.useCar("李四经理","2024年3月16日");
    }

运行结果:
直接用目标类仅做了基础功能,通过代理类在执行目标类的功能前后做了一些前置和后置的业务扩展。
在这里插入图片描述

2、动态代码示例

// 1、定义规范接口
public interface CarApply {
    void useCar(String user, String date);
}
// 2、创建实现类
public class EmployeeCarApply implements CarApply {
    @Override
    public void useCar(String user, String date) {
        System.out.println(user+"在"+date+"申请用车");
    }
}
// 3、创建InvocationHandler的实现类,标识动态代理,进行接口功能转发到本类的invoke方法上
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;

public class CarApplyInvocationHandler implements InvocationHandler {
    private Object target;
    public CarApplyInvocationHandler(Object target){
        this.target = target;
    }
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        System.out.println("调用之前的逻辑");
        Object result = method.invoke(target, args);   // 执行真实的方法
        System.out.println("调用之后的逻辑");
        return result;
    }
}
// 4、创建Proxy的代理工厂,通过此工厂动态生成代理对象
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Proxy;
public class ProxyFactory {
    public static <T> T getProxyInstance(Object target){
        ClassLoader classLoader = target.getClass().getClassLoader();
        Class<?>[] interfaces = target.getClass().getInterfaces();
        InvocationHandler handler = new CarApplyInvocationHandler(target);
        return (T) Proxy.newProxyInstance(classLoader,interfaces,handler);
    }
}
// 5、测试
public static void main(String[] args) {
        CarApply proxyObj = ProxyFactory.getProxyInstance(new EmployeeCarApply());
        proxyObj.useCar("张三","2023年3月17日");
    }

运行结果:
由下结果可以看出,当执行代理对象的业务方法时,之际执行了InvocationHandler实现类的invoke方法。
在这里插入图片描述

3、总结
代理的作用就是在不改变原代码的同时,对原代码的功能做业务扩展。分为静态和动态两种代理方式,静态代理需要我们在开发过程中就先创建好代理的类,直接使用代理类完成原始类的功能,思路和设计也都比较简单。动态代理则是在运行时段,基于反射生成代理类的源码,主要用到了两个对象(Proxy和InvocationHandler接口),相对静态代理而言,代码编写上难度大一点,但是动态代理方式无需大量编写代理对象,如果原始类放生变动,静态代理则是比较奔溃的局面,代理类往往也需要改动,动态代理则相对改动较少。各有优缺点,建议可以在代理类比较少的情况下使用静态代理,其他情况使用动态代理,不确定情况也使用动态代理,多写两次就会写了。

学海无涯苦作舟!!!

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

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

相关文章

本地的git仓库和远程仓库

文章目录 1. 远程创建仓库2. 关联远程和本地代码3. 推送本地分支到远程 1. 远程创建仓库 2. 关联远程和本地代码 上面创建完后会得到一个git仓库的链接&#xff0c;有SSH或者http的 http://gitlab.xxxxx.local:18080/xxxxx/dvr_avm.git ssh://gitgitlab.xxxxx.local:10022/xx…

移动硬盘无法被识别怎么办?恢复移动硬盘3个正确做法

移动硬盘已成为我们日常生活和工作中不可或缺的数据存储设备。然而当移动硬盘突然无法被电脑识别时&#xff0c;往往会让人倍感焦虑。面对这种情况我们不必过于慌张&#xff0c;下面一起来看看指南解决。 解决方法一&#xff1a;检查硬件连接与供电 检查接口连接&#xff1a…

C++面向对象三大特性之---多态

一、多态的概念 多态的概念&#xff1a;通俗来说&#xff0c;就是多种形态&#xff0c;具体点就是去完成某个行为&#xff0c;当不同的对象去完成时会 产生出不同的状态。比如同样是买票的操作&#xff0c;学生买票就会打折&#xff0c;而普通的成人买票就是全款。 二、多态的…

ChatGPT变懒原因:正在给自己放寒假!已被网友测出

ChatGPT近期偷懒严重&#xff0c;有了一种听起来很离谱的解释&#xff1a; 模仿人类&#xff0c;自己给自己放寒假了&#xff5e; 有测试为证&#xff0c;网友Rob Lynch用GPT-4 turbo API设置了两个系统提示&#xff1a; 一个告诉它现在是5月&#xff0c;另一个告诉它现在是1…

【go项目01_学习记录03】

学习记录 1 路由http.ServeMux1.1 查看HandleFunc方法源码1.2 查看ListenAndServe方法源码1.3 重构&#xff1a;使用自定义的 ServeMux1.4 http.ServeMux 的局限性1.4.1 URI 路径参数1.4.2 请求方法过滤1.4.3 不支持路由命名 1.5 http.ServeMux 的优缺点 1 路由http.ServeMux …

当下大模型的趋势以及如何让学习大模型?

当下大模型的趋势 近年来&#xff0c;随着计算能力的提升、数据量的增加以及算法的进步&#xff0c;大模型在人工智能领域展现出了显著的发展趋势。以下是截至2024&#xff0c;大模型发展的一些关键趋势&#xff1a; 参数规模持续增长&#xff1a;从OpenAI的GPT-3的1750亿参数…

森林消防的新利器:高扬程水泵的应用与优势/恒峰智慧科技

森林是地球上的绿色肺叶&#xff0c;保护森林安全对于维护生态平衡和人类生存环境至关重要。在森林消防领域&#xff0c;高效、快速的灭火设备是保障森林安全的重要武器。近年来&#xff0c;高扬程水泵作为一种新型的消防设备&#xff0c;在森林消防中发挥了重要作用。本文将详…

python多标签图像分类的图片相册共享交流系统vue+django

建立图片共享系统&#xff0c;进一步提高用户对图片共享信息的查询。帮助用户和管理员提高工作效率&#xff0c;实现信息查询的自动化。使用本系统可以轻松快捷的为用户提供他们想要得到的图片共享信息。 根据本系统的基本设计思路&#xff0c;本系统在设计方面前台采用了pytho…

IPO压力应变桥信号处理系列隔离放大器 差分信号隔离转换0-10mV/0-20mV/0-±10mV/0-±20mV转4-20mA/0-5V/0-10V

概述&#xff1a; IPO压力应变桥信号处理系列隔离放大器是一种将差分输入信号隔离放大、转换成按比例输出的直流信号混合集成厚模电路。产品广泛应用在电力、远程监控、仪器仪表、医疗设备、工业自控等行业。该模块内部嵌入了一个高效微功率的电源&#xff0c;向输入端和输出端…

ubuntu20.04 手动配置docker下autoware.universe环境

使用docker手动安装autoware环境&#xff0c;参考文章&#xff0c;中间踩过很多坑&#xff0c;特此记录一下。我电脑配置如下&#xff0c;有同样配置的小伙伴可以参考安装&#xff1a; ubuntu20.04cuda: cuda-11.6ros2: foxy 一、手动安装ros2、cuda等 1.1 ROS2安装 推荐使用…

04-23 周二 shell环境下读取使用jq 读取json文件

04-23 周二 shell环境下读取使用jq 读取json文件 时间版本修改人描述04-23V0.1宋全恒新建文档 简介 工具列表 Shell脚本处理JSON数据工具jq jshon是另外一个读取json数据的工具 而且其支持XML和YAML格式文件 linux shell环境下处理yml文件 #!/bin/bash# 加载shyaml库 . /…

在java类前添加上文档注释

第一步&#xff1a; 第二步 第三步 将下面代码粘上 /** *Author Lnn *Date ${DATE}/${TIME} *ClassName ${NAME} *Description */

限量背包问题

问题描述 限量背包问题&#xff1a;从m个物品中挑选出最多v个物品放入容量为n的背包。 问题分析 限量背包问题&#xff0c;可以用来解决许多问题&#xff0c;例如要求从n个物品中挑选出最多v个物品放入容量为m的背包使得背包最后的价值最大&#xff0c;或者总共有多少种放法…

先进制造业数字化转型,为什么基于传统存储无法完成?

本文是 XSKY 智能存储方案助力先进制造数字化转型系列文章中的第一篇&#xff0c;重点分享先进制造行业数字化转型过程中&#xff0c;对于数据存储的需求&#xff0c;以及为何传统存储架构无法很好满足这些需求。 随着智能制造的发展&#xff0c;自动化、信息化、智能化等技术…

unity基础(二)

debug方法 Debug.Log(" 一般日志 ");Debug.LogWarning(" 警告日志 ");Debug.LogError(" 错误日志 ");// Player Informationstring strPlayerName "Peter";int iPlayerHpValue 32500;short shPlayerLevel 10;long lAdvantureExp 1…

k8s部署Kubeflow v1.7.0

文章目录 环境介绍部署访问kubeflow ui问题记录 环境介绍 K8S版本&#xff1a;v1.23.17&#xff0c;需要配置默认的sc 参考&#xff1a;https://github.com/kubeflow/manifests/tree/v1.7.0 部署 #获取安装包 wget https://github.com/kubeflow/manifests/archive/refs/tag…

【方法】如何创建RAR格式压缩文件?

为了方便存储或者传输文件&#xff0c;我们经常会把文件打包成不同格式的压缩包&#xff0c;那如果想创建的是RAR格式的压缩包&#xff0c;要如何做呢&#xff1f; RAR是WinRAR软件独有的压缩格式&#xff0c;所以我们可以通过WinRAR软件来创建RAR格式压缩包。下面分享两种创建…

5000亿参数来了:微软将推出 MAI-1 模型硬刚谷歌和OpenAI|TodayAI

美国的科技巨头微软公司&#xff0c;正在积极扩展其人工智能&#xff08;AI&#xff09;技术的领域。最新消息显示&#xff0c;微软将推出一款名为MAI-1的全新AI模型&#xff0c;其规模巨大&#xff0c;预计将拥有5000亿个可调参数。这一开发工作由Inflection AI的CEO穆斯塔法苏…

cmake进阶:变量的作用域说明三(从函数作用域方面)

一. 简介 前一篇文章从函数作用域方面学习了 变量的作用域。文章如下&#xff1a; cmake进阶&#xff1a;变量的作用域说明一&#xff08;从函数作用域方面&#xff09;-CSDN博客cmake进阶&#xff1a;变量的作用域说明二&#xff08;从函数作用域方面&#xff09;-CSDN博客…

在Node.js(express 框架)中使用 JWT 进行身份认证

文章目录 一、JWT 认证机制二、安装 JWT 相关的包三、基本使用1、生成 JWT 字符串2、添加中间件&#xff0c;解析 JWT 字符串3、获取管理员信息(admin) 一、JWT 认证机制 JWT 认证机制&#xff08;图片来源于网络&#xff0c;侵权删除&#xff09;&#xff1a; 关于 JWT 原理可…