Java设计模式-代理模式

news2024/12/23 23:01:02

简介

代理模式是一种结构型设计模式,它可以让我们通过一个代理对象来访问一个真实的目标对象,从而实现对目标对象的功能扩展或保护。代理模式的主要角色有三个:

  • 抽象主题(Subject):定义了真实主题和代理主题的公共接口,使得在任何使用真实主题的地方都可以使用代理主题。
  • 真实主题(RealSubject):实现了抽象主题的接口,定义了真实的业务逻辑,是代理主题所代表的真实对象。
  • 代理主题(Proxy):也实现了抽象主题的接口,但是在调用真实主题的方法之前或之后,可以执行一些额外的操作,从而对真实主题进行控制或增强。

代理模式可以帮助我们解决以下几种问题:

  • 当我们无法或不想直接访问一个对象时,可以通过一个代理对象来间接访问,例如远程代理、虚拟代理等。
  • 当我们想要给一个对象提供额外的功能时,可以通过一个代理对象来实现,而不需要修改原有的对象,例如缓存代理、日志代理等。
  • 当我们想要给一个对象增加一些访问控制或安全保护时,可以通过一个代理对象来实现,例如防火墙代理、权限代理等。

实现

根据代理模式的定义,我们可以用以下的类图来表示它的结构:

image-20230505112244447

其中,Client是客户端类,它需要使用Subject接口提供的方法。Proxy是代理类,它持有一个RealSubject的引用,并且实现了Subject接口。RealSubject是真实类,它也实现了Subject接口,并且定义了具体的业务逻辑。

代理模式有多种类型,例如静态代理、动态代理等,代理模式也有自己的优缺点,使用时需要根据具体的场景和需求来选择合适的类型和方式。

静态代理实现

下面我们用Java代码来实现一个静态代理的例子:

// 抽象主题接口
public interface Subject {
    // 定义一个抽象方法
    void request();
}

// 真实主题类
public class RealSubject implements Subject {
    // 实现抽象方法
    @Override
    public void request() {
        // 真实的业务逻辑
        System.out.println("RealSubject is doing something...");
    }
}

// 代理主题类
public class Proxy implements Subject {
    // 持有一个真实主题的引用
    private RealSubject realSubject;

    // 构造方法,传入一个真实主题对象
    public Proxy(RealSubject realSubject) {
        this.realSubject = realSubject;
    }

    // 实现抽象方法
    @Override
    public void request() {
        // 在调用真实主题之前,可以执行一些额外操作
        System.out.println("Proxy is doing something before...");
        // 调用真实主题的方法
        realSubject.request();
        // 在调用真实主题之后,可以执行一些额外操作
        System.out.println("Proxy is doing something after...");
    }
}

// 客户端类
public class Client {
    public static void main(String[] args) {
        // 创建一个真实主题对象
        RealSubject realSubject = new RealSubject();
        // 创建一个代理对象,并传入真实主题对象
        Proxy proxy = new Proxy(realSubject);
        // 使用代理对象来调用抽象方法
	    proxy.request();
	}
}
运行结果如下:
Proxy is doing something before...
RealSubject is doing something...
Proxy is doing something after...

从运行结果可以看出,代理对象在调用真实对象的方法之前和之后,都执行了一些额外的操作,从而对真实对象进行了增强或控制。

动态代理实现

动态代理是一种特殊的代理模式,它可以在运行时动态地创建代理对象,而不需要事先定义代理类。动态代理可以更灵活地适应不同的场景和需求,但是也更复杂和难以理解。

这个例子是使用JDK动态代理来实现一个日志代理,它可以在调用目标对象的方法之前和之后,记录相关的日志信息。代码如下:

// 抽象主题接口
public interface Subject {
    // 定义一个抽象方法
    void request();
}

// 真实主题类
public class RealSubject implements Subject {
    // 实现抽象方法
    @Override
    public void request() {
        // 真实的业务逻辑
        System.out.println("RealSubject is doing something...");
    }
}

// 日志处理器类,实现了InvocationHandler接口,用于定义代理逻辑
public class LogHandler implements InvocationHandler {
    // 持有一个目标对象的引用
    private Object target;

    // 构造方法,传入一个目标对象
    public LogHandler(Object target) {
        this.target = target;
    }

    // 实现invoke方法,用于调用目标对象的方法,并在之前和之后执行日志操作
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        // 在调用目标对象之前,记录开始时间
        long startTime = System.currentTimeMillis();
        System.out.println("开始执行" + method.getName() + "方法...");
        // 调用目标对象的方法,并获取返回值
        Object result = method.invoke(target, args);
        // 在调用目标对象之后,记录结束时间和耗时
        long endTime = System.currentTimeMillis();
        long duration = endTime - startTime;
        System.out.println("结束执行" + method.getName() + "方法,耗时" + duration + "毫秒");
        // 返回结果
        return result;
    }
}

// 客户端类
public class Client {
    public static void main(String[] args) {
        // 创建一个真实主题对象
        RealSubject realSubject = new RealSubject();
        // 创建一个日志处理器对象,并传入真实主题对象
        LogHandler logHandler = new LogHandler(realSubject);
        // 使用Proxy类的静态方法newProxyInstance来动态地创建一个代理对象,传入真实主题对象的类加载器、接口和处理器
        Subject proxy = (Subject) Proxy.newProxyInstance(realSubject.getClass().getClassLoader(), realSubject.getClass().getInterfaces(), logHandler);
        // 使用代理对象来调用抽象方法
        proxy.request();
    }
}

运行结果如下:

开始执行request方法...
RealSubject is doing something...
结束执行request方法,耗时1毫秒

从运行结果可以看出,代理对象在调用真实对象的方法之前和之后,都执行了一些日志操作,从而对真实对象进行了增强。

优缺点

静态代理模式

优点:

  • 代理模式可以实现对真实对象的功能扩展或保护,而不需要修改原有的对象,符合开闭原则。
  • 代理模式可以实现对真实对象的访问控制或延迟加载,提高系统的性能和安全性。
  • 代理模式可以实现对真实对象的透明访问,客户端只需要使用抽象主题的接口,而不需要关心真实对象和代理对象的细节。

缺点:

  • 代理模式会增加系统的复杂度和开销,因为需要创建和维护代理对象。
  • 代理模式可能会降低系统的响应速度,因为每次调用真实对象的方法都需要经过代理对象。

动态代理模式

优点:

  • 动态代理可以在运行时动态地创建代理对象,而不需要事先定义代理类,这样可以减少代码量和提高开发效率。
  • 动态代理可以根据不同的目标对象和需求,灵活地生成不同的代理对象,这样可以增加系统的可扩展性和可维护性。
  • 动态代理可以实现对目标对象的透明访问,客户端只需要使用抽象主题的接口,而不需要关心真实对象和代理对象的细节。

缺点:

  • 动态代理需要使用反射和字节码技术来生成代理对象,这样会增加系统的复杂度和开销,也可能会影响系统的性能和稳定性。
  • 动态代理需要遵循一些约束和限制,例如JDK动态代理只能代理实现了接口的类,CGLIB动态代理不能代理final类或方法等,这样会降低系统的灵活性和通用性。
  • 动态代理比静态代理更难以理解和掌握,需要有一定的基础知识和经验才能使用好动态代理。

运用场景

  • 当我们需要访问一个远程对象时,可以使用远程代理,它可以隐藏远程对象的位置和通信细节,让客户端像访问本地对象一样访问远程对象。
  • 当我们需要创建一个开销很大的对象时,可以使用虚拟代理,它可以在真正需要的时候才创建真实对象,从而实现延迟加载和节省资源。
  • 当我们需要给一个对象增加一些额外的功能时,可以使用装饰代理,它可以在不修改原有对象的情况下,给对象添加一些新的行为或属性。
  • 当我们需要给一个对象增加一些访问控制或安全保护时,可以使用保护代理,它可以根据不同的用户或角色,对对象的访问进行限制或检查。
  • 当我们需要给一个对象增加一些日志记录或性能监控时,可以使用日志代理或性能代理,它可以在调用对象的方法之前或之后,记录相关的信息或数据。

总结

代理模式是一种常用的结构型设计模式,它可以让我们通过一个代理对象来间接访问一个真实对象,从而实现对目标对象的功能扩展或保护。代理模式有三个主要角色:抽象主题、真实主题和代理主题。代理模式有多种类型,例如静态代理、动态代理、远程代理、虚拟代理等。代理模式有自己的优缺点,使用时需要根据具体的场景和需求来选择合适的类型和方式。

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

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

相关文章

Prompt 技巧指南-让 ChatGPT 回答准确十倍!

出品人:Towhee 技术团队 作者:张晨 随着 ChatGPT 等大型语言模型 (LLM)的兴起,人们慢慢发现,怎么样向 LLM 提问、以什么技巧提问,是获得更加准确的回答的关键,也由此产生了提示工程这个全新的领域。 提示工…

JavaScript实现输入班级人数和成绩后,输出总成绩、平均成绩、最高分、最低分的代码

以下为实现输入班级人数和成绩输出总成绩、平均成绩、最高分、最低分的代码和运行截图 目录 前言 一、实现输入班级人数和成绩,输出总成绩、平均成绩、最高分、最低分的代码 1.1 运行流程及思想 1.2 代码段 1.3 JavaScript语句代码 1.4 运行截图 前言 1.若有…

JavaWeb《后端内容:1.Tomcat--Servlet--Thymeleaf》

目录 1. 基础概念 1.1 BS架构和CS架构 1.2 Tomcat图解 2.TomCat 2.1 IDEA配置web项目和tomcat 2.2 idea启动TomCat因为端口号失败的问题 3.Servlet使用流程 3.1 Servlet简单图解 3.2 Servlet导入依赖 3.3 编写Servlet和add.html 3.4 试着使用Jdbc和Dao层连接水果库存…

超细Redis(一)

目录 概述 Redis是什么? Redis能干嘛? 特性 如何学习 Linux安装 测试性能 概述 Redis是什么? Redis (Remote Dictionary Server),即远程字典服务 是一个开源使用ANSI C语言编写、支持网络、可基于内存亦可持…

阿里版ChatGPT——通义千问,开箱初体验

所有行业、所有应用、所有服务都值得基于新型人工智能技术重做一遍,在带来创造性客户体验的同时,生产范式、工作范式、生活范式也将发生变化。——阿里集团董事会主席兼CEO 张勇 2023阿里云峰会上,通义千问大语言模型对外发布,宣称…

【语义分割】LinkNet 从0到1 和代码实现

文章目录 前言1.网络结构1.1 网络结构示意图1.2 创建LinkNet模型 2.代码 前言 已经有了U-net了,为什么需要linkNet? unet见这个文章【语义分割】unet结构和代码实现:https://blog.csdn.net/weixin_40293999/article/details/129648032 它引入了resNet&a…

“SDL 入门指南:了解 SDL,快速上手 SDL 的安装和配置”——VS2022

前言 欢迎来到小K的SDL专栏第一小节,本节为大家介绍一下SDL是什么,能做什么,可以在哪些平台运行以及SDL的安装和VS2022配置SDL、导出模板、cmake运行SDL,同时我也会在资源里为大家上传SDL2.26的安装包,为在github上下载…

扫地机洗地机语音芯片ic一体方案 WTV多功能语音芯片

​随着智能家居的快速普及,扫拖一体机语音芯片ic逐渐成为了家庭清洁的必备之物。在智能家居、商业清洁服务、医院清洁服务、办公室清洁等领域得到广泛应用;而语音芯片方案的应用让清洁机器设备使用起来更加方便和智能化。 编辑搜图 目前大多数扫地机厂家…

2023/5/4总结

刷题&#xff1a; 第二周任务 - Virtual Judge (vjudge.net) 这一题用到了素筛,然后穷举即可 #include<stdio.h> #define Maxsize 500000 int a[Maxsize]; long long b[Maxsize]; long long max0; int sushu() {a[0]a[1]0;int i,j,k;for(i2,k0;i<Maxsize;i){if(a[i…

jeecgboot online代码生成 一对多

首先把前后端环境都起起来&#xff0c;此处略 点击online表单开发&#xff0c;设计主附表&#xff0c;表示一对多(一对一)关系&#xff0c;“一”对应主表&#xff0c;“多”对应附表&#xff0c;如图 表设计完成&#xff0c;点击同步可直接在数据库中生成数据表。 附表注意…

卢北辰:数据点亮梦想,能力驱动人生 | 提升之路系列(九)

导读 为了发挥清华大学多学科优势&#xff0c;搭建跨学科交叉融合平台&#xff0c;创新跨学科交叉培养模式&#xff0c;培养具有大数据思维和应用创新的“π”型人才&#xff0c;由清华大学研究生院、清华大学大数据研究中心及相关院系共同设计组织的“清华大学大数据能力提升项…

今天的事务的基础上继续找出错点

今天的事务的基础上继续找出错点 2023-05-05 08:21:40.362 ERROR 5560 --- [nio-8080-exec-7] o.a.c.c.C.[.[.[/].[dispatcherServlet] : Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Request processing failed; nested…

手机摄影笔记(一)

人像裁剪注意&#xff1a; 不要在人像的脚踝&#xff0c;膝盖&#xff0c;手肘&#xff0c;手腕处进行裁剪&#xff0c;这样会显得残缺&#xff0c;因为这些位置属于转折位置&#xff0c;不光滑的&#xff0c;上下差别很大。而在手臂&#xff0c;大腿等其他地方进行裁剪&#x…

ThingsBoard教程(三八):规则节点解析 筛选脚本 script,路由分支 switch

前言 本篇文件继续介绍规则节点中的 筛选类型的节点, 筛选脚本 script 可以通过js编程,使用消息体中的书籍,来实现返回true或false。 路由分支 switch : 将传入消息路由到一个或多个输出连接。节点执行配置的TBEL(推荐)或返回字符串数组(连接名称)的JavaScript函数。 …

《花雕学AI》30:ChatGPT的资料来源比例排名前20名是什么?

引言&#xff1a;ChatGPT是一款由OpenAI开发的人工智能聊天机器人&#xff0c;它可以回答各种问题&#xff0c;并生成创意内容&#xff0c;如诗歌、故事、代码等。 ChatGPT的核心技术是基于GPT-3.5和GPT-4的大型语言模型&#xff0c;它可以利用从网路上收集的大量文本资料来进行…

《一》Node 基础

Node&#xff1a;是一个基于 V8 引擎的 JavaScript 运行的环境。 V8 引擎可以嵌入到任何 C 应用程序中&#xff0c;无论是 Chrome 浏览器还是 Node&#xff0c;事实上都是嵌入了 V8 引擎来执行 JavaScript 代码的。 Node 架构&#xff1a; 编写的 JavaScript 代码首先经过 V8 引…

Springframework和Hibernate版本对应关系

org.springframework 3.0.x对应org.hibernate4.0.x版本 org.springframework 3.2.x对应org.hibernate4.2.x版本 org.springframework 4.0.x对应org.hibernate4.3.x版本 org.springframework 4.1.x对应org.hibernate5.0.x版本 org.springframework 4.3.x对应org.hibernate5.…

TOB企业如何构建自身的生态力

众所周知&#xff0c;企业服务赛道业务涉及范围非常多&#xff0c;其面向的客户分布广、触达过程长、需求场景复杂、功能集成和持续服务要求高等特点&#xff0c;就决定了To B企业无法通过单枪匹马的运营模式&#xff0c;来满足增长和健康运营的需求。 随着市场的竞争日益加剧…

【Docker】镜像与docker数据卷

文章目录 一、镜像1、镜像2、镜像原理之联合文件系统3、镜像原理之分层4、commit镜像 二、数据卷1、数据卷2、-v使用数据卷3、实战&#xff1a;MySQL 同步数据4、docker volume相关指令5、匿名和具名挂载6、数据卷之Dockerfile7、数据卷容器 一、镜像 1、镜像 镜像是一种轻量级…

k8s笔记25--k8s 跨主机网络flannel

k8s笔记25-- k8s 跨主机网络flannel 简介不同机器上网络设备区别flannel 网络常见三大后端模式UDPVXLANhost-gw 如何查看集群用哪种网络模式阿里云flannel容器网络 alloc参考文档 简介 在单机环境下&#xff0c;容器间可以通过 docker0 网桥来通信&#xff0c;但其无法实现不同…