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

结构型模式之代理模式

  • 一、概念和使用场景
    • 1、概念
    • 2、核心思想
    • 3、java实现代理模式的方式
    • 4、使用场景
  • 二、示例讲解
    • 1. 静态代理
    • 2. 动态代理
  • 三、总结
    • 1、使用规则
    • 2、代理模式的优点包括:
    • 3、代理模式的缺点包括:

一、概念和使用场景

1、概念

代理模式是一种结构型设计模式,它允许我们为其他对象提供一个代理或者占位符,以控制对该对象的访问。

2、核心思想

代理模式的核心思想是在访问一个对象时引入一个代理对象,通过代理对象来控制访问的权限和行为。代理对象和被代理对象具有相同的接口,这样客户端就可以通过代理对象来访问被代理对象。代理对象可以拦截对被代理对象的访问,并添加额外的逻辑,例如权限检查、缓存等。

3、java实现代理模式的方式

在Java中实现代理模式有两种方式:静态代理和动态代理

4、使用场景

Java代理模式的使用场景有以下几个:

  1. 远程代理:当对象存在不同地址空间时,可以使用远程代理来隐藏对象的具体实现细节,使得客户端可以像访问本地对象一样访问远程对象。远程代理主要用于网络通信中的远程方法调用。

  2. 虚拟代理:当创建一个对象需要很长时间时(例如加载大量数据或者进行复杂的计算),可以使用虚拟代理来延迟对象的创建。虚拟代理在真正需要使用对象时才会创建,可以节省系统资源。

  3. 安全代理:当需要控制对某个对象的访问权限时,可以使用安全代理来限制对对象的直接访问。安全代理可以在访问对象之前进行权限验证,确保只有具有相应权限的用户才能访问对象。

  4. 缓存代理:当需要缓存对象的结果时,可以使用缓存代理来提高系统的性能。缓存代理会在调用对象的方法之前检查缓存,如果缓存中已经存在相同的结果,则直接返回缓存中的结果,而不去真正执行方法。

  5. 日志记录代理:当需要记录对象的操作日志时,可以使用日志记录代理来实现。日志记录代理会在调用对象的方法之前进行日志记录,可以记录下对象的操作信息,方便后续的审计和分析。

总之,代理模式可以在不改变原有对象的情况下,通过引入代理对象来增加一些额外的功能,提供更好的控制和封装。

二、示例讲解

1. 静态代理

静态代理是在编译时就已经确定代理对象的类型,代理对象和被代理对象都需要实现同一个接口。代理对象在调用被代理对象的方法前后可以执行一些额外的逻辑。

下面是一个简单的静态代理的示例代码:
定义一个接口 SaleHouse

//待出售房产
public interface SaleHouse {//房产信息Object    houseInformation(String price);
}

被代理的角色(房子主人) HouseOwner

package org.storemanage.regestercenter.proxymode;/*** @CreateTime: 2024-08-30* @Description: 房屋主人* @Version: 1.0* @Author: hkf*/public class HouseOwner implements SaleHouse {private final String  name ="阳光别墅区";private final  String address ="四川省成都市武侯区双楠大道xxx小区123号";private String price;@Overridepublic Object houseInformation(String price) {String  houseInfo ="200 W";if (!price.isEmpty()) {houseInfo=  "房产名称:"+name+"\n 地址为:"+address+"\n房产价格为:"+price;}return houseInfo ;}public String getPrice() {return price;}public void setPrice(String price) {this.price = price;}@Overridepublic String toString() {return "HouseOwner{" +"name='" + name + '\'' +", address='" + address + '\'' +", price='" + price + '\'' +'}';}
}

代理角色 (房屋中介) HouseAgent

package org.storemanage.regestercenter.proxymode;/*** @CreateTime: 2024-08-30* @Description: 房屋中介* @Version: 1.0* @Author: hkf*/public class HouseAgent implements SaleHouse {private   String  price;public String getPrice() {return price;}public void setPrice(String price) {this.price = price;}HouseOwner  houseOwner;//中介为了赚佣金,提高了出售的价格@Overridepublic Object houseInformation(String price) {Object houseInfo ="";if (houseOwner == null) {houseOwner = new HouseOwner();houseInfo = houseOwner.houseInformation(price);}return houseInfo;}@Overridepublic String toString() {return "HouseAgent{" +"price='" + price + '\'' +", houseOwner=" + houseOwner +'}';}
}

客户端调用者 ClientHouseAgent

package org.storemanage.regestercenter.proxymode;/*** @CreateTime: 2024-08-30* @Description: 客户端代理实现* @Version: 1.0* @Author: hkf*/public class ClientHouseAgent {public static void main(String[] args) {HouseAgent houseAgent = new HouseAgent();//中介可以自定义价格,赚取佣金Object houseInfo = houseAgent.houseInformation("236 w");System.out.println(houseInfo);}}

结果如图
在这里插入图片描述

2. 动态代理

动态代理是在运行时通过反射机制动态生成代理对象,代理对象不需要实现接口,但需要指定一个接口或者父类来实现代理。

下面是一个简单的动态代理的示例代码:

定义接口 SaleHouse

package org.storemanage.regestercenter.proxymode;//待出售房产
public interface SaleHouse {//房产信息Object    houseInformation(String price);
}

定义被代理角色 HouseOwner

package org.storemanage.regestercenter.proxymode;/*** @CreateTime: 2024-08-30* @Description: 房屋主人* @Version: 1.0* @Author: hkf*/public class HouseOwner implements SaleHouse {private final String  name ="阳光别墅区";private final  String address ="四川省成都市武侯区双楠大道xxx小区123号";private String price;@Overridepublic Object houseInformation(String price) {String  houseInfo ="200 W";if (!price.isEmpty()) {houseInfo=  "房产名称:"+name+"\n 地址为:"+address+"\n房产价格为:"+price;}return houseInfo ;}public String getPrice() {return price;}public void setPrice(String price) {this.price = price;}@Overridepublic String toString() {return "HouseOwner{" +"name='" + name + '\'' +", address='" + address + '\'' +", price='" + price + '\'' +'}';}
}

创建代理角色 HouseAgentInvocationHandler

package org.storemanage.regestercenter.proxymode;import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;/*** @CreateTime: 2024-08-30* @Description: 中介动态代理* @Version: 1.0* @Author: hkf*/public class HouseAgentInvocationHandler implements InvocationHandler {private Object  target;public HouseAgentInvocationHandler(Object  target){this.target = target;}@Overridepublic Object invoke(Object proxy, Method method, Object[] args) throws Throwable {System.out.println("Before method: " + method.getName());Object invoke = method.invoke(target, args);System.out.println(" After  method: " + method.getName());return invoke;}
}

客户端代码 ClientHouseDemo

package org.storemanage.regestercenter.proxymode;import java.lang.reflect.Proxy;/*** @CreateTime: 2024-08-30* @Description: 动态代理客户端代码* @Version: 1.0* @Author: hkf*/public class ClientHouseDemo {public static void main(String[] args) {HouseOwner houseOwner = new HouseOwner();HouseAgentInvocationHandler handler = new HouseAgentInvocationHandler(houseOwner);SaleHouse saleHouse=(SaleHouse)Proxy.newProxyInstance(houseOwner.getClass().getClassLoader(), houseOwner.getClass().getInterfaces(),handler);Object o1 = saleHouse.houseInformation("443 W");System.out.println(o1);}
}

结果如图
在这里插入图片描述
在上述代码中,我们首先定义了一个接口 SaleHouse ,然后实现了该接口的具体类 HouseOwner 。接着,定义了 HouseAgentInvocationHandler 类作为动态代理的 InvocationHandler ,在 invoke 方法中可以添加额外的逻辑。在客户端代码中,我们创建了 HouseOwner 对象和 HouseAgentInvocationHandler 对象,然后利用 Proxy 类的 newProxyInstance 方法生成代理对象,最后调用代理对象的 houseInformation 方法。

三、总结

1、使用规则

无论是静态代理还是动态代理,代理模式都可以在不改变被代理对象的情况下,对访问进行控制和添加额外的逻辑。代理模式可以提高代码的可维护性和可扩展性,但也会增加代码的复杂性和性能开销,因此在使用代理模式时需要根据具体的情况进行权衡。

2、代理模式的优点包括:

  1. 代理模式可以实现真实对象的延迟加载。当真实对象的创建和初始化过程比较耗时时,使用代理模式可以在需要的时候才创建真实对象,提高系统的性能和响应速度。

  2. 代理模式可以提供额外的安全性控制。通过代理对象来控制对真实对象的访问,可以在访问前后进行一些额外的安全性检查和操作,增加系统的安全性。

  3. 代理模式可以实现对真实对象的访问控制和管理。通过代理对象可以控制对真实对象的访问和调用,可以实现一些额外的管理功能,如权限控制、缓存管理等。

3、代理模式的缺点包括:

  1. 代理模式增加了系统的复杂度。引入代理对象会增加系统中的类和对象的数量,增加系统的复杂度和维护成本。

  2. 代理模式可能会引入性能问题。由于代理模式引入了额外的层次,可能会在一定程度上降低系统的性能,特别是在频繁访问真实对象的情况下。

  3. 代理模式的设计需要考虑到代理对象和真实对象之间的接口的一致性,使得系统的设计和实现更加复杂。

在这里插入图片描述

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

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

相关文章

HUD杂散光环境模拟测试设备

概述 HUD(Head-Up Display)杂散光环境模拟测试设备是用于模拟飞行器在实际运行过程中可能遇到的多种光照环境的系统。它主要用于测试和验证HUD显示系统的性能,确保其能在各种光线条件下清晰、准确地显示信息,从而保障飞行员在复杂…

【大模型理论篇】通用大模型架构分类及技术统一化

1. 背景 国内的 “百模大战” 以及开源大模型的各类评测榜单令人眼花缭乱,极易让人陷入迷茫。面对如此众多的大模型,我们该如何审视和选择呢?本文将从大模型架构的角度,对常见的开源大模型架构进行汇总与分析。资料来源于公开…

2024全国大学生数学建模国赛,成员如何分工协作?

文末获取2024国赛数学建模思路代码,9.5开赛后第一时间更新 大家知道,数学建模竞赛是需要一个团队的三个人在三天或四天的时间内,完成模型建立,编程实现和论文写作的任务,对许多第一次参加建模或者建模经验比较欠缺的团…

Android 使用原生相机Camera在预览界面进行识别二维码或者图片处理

1 项目需求 最近项目中有个需求:使用原生相机在预览界面进行识别二维码和图片处理。其实这个需求不是很难,难在对预览画面的处理过程。 自己针对这个需求写了一个工具类,便于后续进行复盘,同时也分享给有类似需求的伙伴们。 2 遇到的问题 2.1 二维码识别成功率低 使用…

由浅入深学习 C 语言:Hello World【提高篇】

目录 引言 1. Hello World 程序代码 2. C 语言角度分析 Hello World 程序 2.1. 程序功能分析 2.2 指针 2.3 常量指针 2.4 指针常量 3. 反汇编角度分析 Hello World 程序 3.1 栈 3.2 函数用栈传递参数 3.3 函数调用栈 3.4 函数栈帧 3.5 相关寄存器 3.6 相关汇编指令…

优化学习管理:Moodle和ONLYOFFICE文档编辑器的完美结合

目录 前言 一、什么是 Moodle 1、简单快速插入表单字段 3、免费表单模板库 4、开启无缝协作 三、在Moodle中集成ONLYOFFICE文档 四、在Moodle安装使用ONLYOFFICE 1、下载安装 2、配置服务器 3、在Moodle中使用ONLYOFFICE 文档活动 五、未来展望 写在最后 前言 在当今教育科技飞…

JVM垃圾回收算法:标记-清除算法 、复制算法、 标记-整理算法、 分代收集算法

文章目录 引言I 标记回收算法(Mark-Sweep)算法不足II 复制算法(Copying)III 标记整理算法(Mark-Compact)IV 分代收集(以上三种算法的集合体)内存划分新生代算法:Minor GC老年代算法V 查看JVM堆分配引言 垃圾回收(Garbage Collection,GC) Java支持内存动态分配、…

Flask+LayUI开发手记(六):树型表格的增删改查

树型表格的增删改查功能与数据表格的是完全一致,就是调用layui-form表单组件实现数据输入再提交,比较大的区别是树型节点的编辑,都需要有上级节点的输入,而这个上级节点的展示,必须是以树型方式展示出来。当然&#xf…

语音控制开关的语音识别ic芯片方案

语音控制开关是一种基于语音识别技术的设备,它通过内置的语音识别芯片,将用户的语音指令转化为电信号,从而实现对设备的控制。例如在智能家居设备上的应用,通常需要连接到家庭的Wi-Fi网络上,以便与智能手机或智能音箱等…

golang RSA 解密前端jsencrypt发送的数据时异常 crypto/rsa: decryption error 解决方法

golang中 RSA解密前端(jsencrypt)发来的密文后出现 "crypto/rsa: decryption error" , 这个问题首先需要确认你的私匙和公匙是否匹配, 如果匹配 那检查入参数据类型, 前端发送来的rsa加密后的数据一般都是…

bbr 随机 phase 的麻烦与 inflight 守恒算法的动机

bbr 有个要点,要把 probebw 的 phase 错开: static void bbr_reset_probe_bw_mode(struct sock *sk) {struct bbr *bbr inet_csk_ca(sk);bbr->mode BBR_PROBE_BW;bbr->cycle_idx CYCLE_LEN - 1 - prandom_u32_max(bbr_cycle_rand);bbr_advance…

Java项目:基于SpringBoot+mysql在线拍卖系统(含源码+数据库+答辩PPT+毕业论文)

一、项目简介 本项目是一套基于SSM框架mysql在线拍卖系统 包含:项目源码、数据库脚本等,该项目附带全部源码可作为毕设使用。 项目都经过严格调试,eclipse或者idea 确保可以运行! 该系统功能完善、界面美观、操作简单、功能齐全、…

Java 面试题:HTTP版本演变--xunznux

文章目录 HTTP版本演变HTTP/0.9HTTP/1.0HTTP/1.1新引入:问题:长连接是什么:管道网络传输:队头阻塞是什么?解决http队头阻塞的方法:HTTP1.1常见性能问题为解决HTTP1.1性能问题而提出的常见优化手段 HTTP/21、…

【河北航空-注册安全分析报告-无验证方式导致安全隐患】

前言 由于网站注册入口容易被黑客攻击,存在如下安全问题: 1. 暴力破解密码,造成用户信息泄露 2. 短信盗刷的安全问题,影响业务及导致用户投诉 3. 带来经济损失,尤其是后付费客户,风险巨大,造…

RS485与USB3.1电路

USB2.0最高也就480M,而USB3.0轻松到达5Gbps: DTU远程控制: DTU(数据传输单元)通常用于将数据从现场设备传输到远程服务器,常用于物联网、工业控制、远程监控等场景。它可以通过GPRS/4G、Wi-Fi、以太网等方…

Python网络爬虫模拟登录与验证解析

内容导读 使用Selenium模拟登录 使用Cookies登录网站 模拟表单登录网站 爬虫识别简单的验证码 实例解析 一、使用Selenium模拟登录 1、为什么要模拟登录 在互联网上存在大量需要登录才能访问的网站,要爬取这些网站,就需要学习爬虫的模拟登录。对…

TC-RAG: Turing-Complete RAG--图灵完备的检索增强

摘要: 在提升领域特定的大语言模型(LLMs)的方法中,检索增强生成(RAG)技术作为一种有前景的解决方案,可以缓解诸如幻觉、知识过时以及在高度专业化查询中专业知识有限等问题。然而,现…

WPF- vs中的WPF应用项目模板 如何自己实现

读书笔记 1. 单个 c#文件的 空白window应用程序 (只展示了一个button按钮) 2.C#文件 和xml文件 的空白window程序 .xml文件作为程序的资源 (只一个button按钮) 3. xmal和c#共同编译 形如使用VS 创建WPF应用项目模板 1.新建一个wpf空白项目 ,添加一个主c#文件 和xaml文件(属…

【C++ Primer Plus习题】7.2

问题: 解答: #include <iostream> using namespace std;#define MAX 10int input(float* grade, int len) {int i 0;for (i 0; i < len; i){cout << "请输入第" << i 1 << "个高尔夫成绩(按0结束):";cin >> grade[i]…