设计模式[5]-代理模式

news/2024/11/17 14:52:33/文章来源:https://www.cnblogs.com/Aeons/p/18375612

代码:https://gitee.com/Aes_yt/design-pattern

代理模式

代理模式需要给某对象提供一个代理来访问该对象。是客户端和目标对象之间的一个媒介。

代理模式主要包括三种角色
  • 抽象主题:接口或抽象类,有着业务方法,可以让真实主题和代理对象来实现。
  • 真实主题:实现了抽象主题的方法,是代理类所代理的真实对象。
  • 代理类:提供了与真实主题相同的接口,其内部含有对真实主题的引用,它可以访问、控制或扩展真实主题的功能。

代理模式又分为静态代理和动态代理,静态代理是程序运行前,.class文件已经存在,而动态代理则是利用反射原理,动态创建类。

例子

我们如果有一个计算类,它在方法中进行复杂计算,然后我们要在计算前后进行日志记录,并统计计算的耗时,这时可以用代理模式来实现。

1. 静态代理

image-20211229000217567

Calculate 抽象主题:

public interface Calculate {long execute(int time);
}

ComplexCalculate 真实主题:

public class ComplexCalculate implements Calculate {/*** 在方法里面进行计算,要用到time参数*/@Overridepublic long execute(int time) {System.out.println("调用了 ComplexCalculate 类中的 execute 方法。参数是" + time);long i = 1;for (int j = 0; j < time; j++) {i += 5;}return i;}
}

ProxyCalculate 代理类:

public class ProxyCalculate implements Calculate {private ComplexCalculate calculate = new ComplexCalculate();@Overridepublic long execute(int time) {long start = System.currentTimeMillis();System.out.println("开始执行");long result = calculate.execute(time);long end = System.currentTimeMillis();System.out.println("结束执行, 耗时:" + (end - start) + " ms");return result;}
}

测试:

    @Testvoid execute() {ProxyCalculate calculate = new ProxyCalculate();long result = calculate.execute(1000000);System.out.println("result:" + result);}

输出:

开始执行
调用了 ComplexCalculate 类中的 execute 方法。参数是1000000
结束执行, 耗时:1 ms
result:5000001

分析:

在ProxyCalculate 代理类中,实现了抽象接口,并且声明了ComplexCalculate真实主题类属性,而实际执行execute方法的则是ComplexCalculate的实例对象。从而实现了通过代理类去访问真实对象,并且在执行方法前可以编写自己的逻辑。

2. 动态代理 jdk

我们用jdk自带的Proxy类来实现动态代理,抽象主题和真实主题不变,和上面的静态代理一样,不同的只是ProxyCalculate 代理类我们改成代理工厂,生成代理对象的实例。

image-20211229000137999

ProxyFactory :

public class ProxyFactory {private ComplexCalculate calculate = new ComplexCalculate();/*** Proxy.newProxyInstance 三个参数:* ClassLoader loader:类加载器* Class<?>[] interfaces:代理类接口字节码* InvocationHandler h:代理对象的调用程序,此处用lambda实现,有三个参数* Object proxy: 代理对象* Method method : 调用方法的method对象* Object[] args : 调用方法的参数*/public Calculate getCalculateObj() {return (Calculate) Proxy.newProxyInstance(calculate.getClass().getClassLoader(),calculate.getClass().getInterfaces(),(proxy, method, args) -> {long start = System.currentTimeMillis();System.out.println("开始执行");// ==== 实际执行的就是这一行,其他的都是额外的自定义逻辑 ====long result = (long) method.invoke(calculate, args);// ==== ======================================= ====long end = System.currentTimeMillis();System.out.println("结束执行, 耗时:" + (end - start) + " ms");return result;});}
}

测试:

@Test
void execute() {ProxyFactory factory = new ProxyFactory();long result = factory.getCalculateObj().execute(1000000);System.out.println("result:" + result);
}

输出:

开始执行
调用了 ComplexCalculate 类中的 execute 方法。参数是1000000
结束执行, 耗时:1 ms
result:5000001

注意:

被代理的真实对象是需要实现接口才可以用Proxy进行代理的,如果类没有实现接口的话,可以引入cglib包进行代理。

优缺点

代理模式的优点有:

  • 可以对目标对象的功能进行拓展,比如上边例子上的日志打印等,

  • 代理模式在客户端与目标对象之间起到一个中介作用和保护目标对象的作用

代理模式的缺点有:

  • 增加系统的复杂性
  • 在目标对象之前又增加了代理对象,会使请求的处理速度变慢

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

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

相关文章

设计模式[2]-工厂模式

代码:https://gitee.com/Aes_yt/design-pattern工厂模式 1. 简单工厂模式 简单工厂模式主要包括三种角色:简单工厂 : 创建具体产品 抽象产品 : 具体产品的父类 具体产品 : 简单工厂创建的对象例子: 设计一个游戏机类(GameConsole) 作为抽象产品,然后设计具体的产品(Plan…

2021-12-29-md1

代码:https://gitee.com/Aes_yt/design-pattern代理模式 代理模式需要给某对象提供一个代理来访问该对象。是客户端和目标对象之间的一个媒介。 代理模式主要包括三种角色抽象主题:接口或抽象类,有着业务方法,可以让真实主题和代理对象来实现。 真实主题:实现了抽象主题的…

dubbo[3]_注解配置

本文介绍注解方式配置dubbo的例子。 服务提供Provider 1. 定义接口Animal和实现类CatAnimal: public interface Animal {/*** 描述: 返回动物的叫声*/String sound(); }Cat: package com.yt.provider;import com.alibaba.dubbo.config.annotation.Service;@Service(timeout = 5…

dubbo[2]_XML配置

本文介绍了zookeeper的下载安装以及用xml配置服务消费者和提供者的例子。 1. zookeeper下载安装 本文的例子使用zookeeper作为注册中心。 首先,从官网下载zookeeper,我选择的是Apache ZooKeeper 3.6.3版本。下载完成后,解压到自己的目录。https://zookeeper.apache.org/rele…

2021-05-13-md1

本文介绍注解方式配置dubbo的例子。 服务提供Provider 1. 定义接口Animal和实现类CatAnimal: public interface Animal {/*** 描述: 返回动物的叫声*/String sound(); }Cat: package com.yt.provider;import com.alibaba.dubbo.config.annotation.Service;@Service(timeout = 5…

2021-05-12-md1

本文介绍了zookeeper的下载安装以及用xml配置服务消费者和提供者的例子。 1. zookeeper下载安装 本文的例子使用zookeeper作为注册中心。 首先,从官网下载zookeeper,我选择的是Apache ZooKeeper 3.6.3版本。下载完成后,解压到自己的目录。https://zookeeper.apache.org/rele…

Myslq千万级数据量查询

两千四百万数据量SQL查询没有索引时 如果字段无索引,耗时十分钟无索引查询过程 MySQL 需要对 2400 万条数据一一进行比较,假设每条记录的处理时间为 0.025 ms,那么总查询时间大约为 10 分钟(即 2400 万 0.025 ms)。 •全表扫描: 当查询 kh = 03356129487 时,如果表上没有…

001.MinIO简介

MinIO 简介 MinIO 是天然的云原生存储,可以作为轻量级容器运行,由相关编排服务(如 Kubernetes )管理。 整个服务器是一个不到100MB的静态二进制文件,并且在使用CPU和内存资源方面即使在高负载场景也非常高效,因此可以在共享硬件上共同托管大量租户。 MinIO 可以在任何地方和…

转载:国产麒麟v10、UOS系统在线比较两个Word文件的内容差异

调用PageOffice的WordCompare方法,同时在线打开两个Word文档,可以切换显示其中的一个文档,或者显示两个文档的对比结果,即可实现在线的文档内容比较功能。此功能可以应用在以下方面: 文档管理中,比较两个版本Word文档的差别。 在处理文档管理的Web项目中,比较两个版本的…

并发编程[5]_wait和notify

1. wait 和 notify wait() 方法是Object类中的方法,他的作用是让当前线程进入等待状态,而使用notify() 方法可以唤醒。wait(long): void ,参数是毫秒,表示等待毫秒数,直到时间结束或被唤醒; wait(long, int): void ,第一个参数是毫秒,第二个参数是纳秒,如果纳秒在0-99…

【2024-08-23】邬贺铨院士:大模型赋能企业数字化转型

一、AI的演进之路:从生成式AI到通用A1二、大模型的构建与应用:自建与协作开发的行业大模型2.1 自建基础大模型2.2 合作开发行业大模型三、对MaaS及其工具链的探索四、大模型推动云服务创新4.1 大模型时代对算力网络的要求4.2 大模型推动IaaS创新发展4.3 大模型催生AI PaaS创新…

.NET 8 + Vue 3 极简 RABC 权限管理系统

前言 在日常工作中,几乎每家公司都需要一个后台管理系统来处理各种任务。为了帮助大家快速搭建这样一个系统,给大家介绍一个基于最新技术 .NET 8 和前端框架 Vue 3 实现的极简 RABC(基于角色的访问控制)权限管理系统。 该系统后端采用经过精心精简的 ABP框架,前端则使用了…