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

结构型模式之代理模式

  • 一、概念和使用场景
    • 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.rhkb.cn/news/412882.html

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

相关文章

笔记:应用Visual Studio Profiler识别和解决内存泄漏问题

一、目的:应用Visual Studio Profiler识别和解决内存泄漏问题 识别和解决内存泄漏问题是确保应用程序稳定性和性能的关键步骤。 二、实现 以下是如何使用 Visual Studio Profiler 识别和解决内存泄漏问题的详细步骤: 1. 启动内存分析 1. 打开项目&…

Windows环境CP Editor安装使用方法

step0:下载软件包,附件有已经下载的安装包 Download CP Editor | CP Editor step1:下载后双击安装即可(记住安装路径) step2:找到安装目录下的cpeditor\mingw64\bin配置环境变量 step3:双击打开即可使用

《王者荣耀》游戏玩法与部分机制分析

目录 游戏机制 MOBA核心玩法 匹配机制 游戏模式 隐藏分机制 游戏规则 总结 王者荣耀的ELO匹配机制是如何具体工作的? 王者荣耀中隐藏分机制的详细规则是什么?(难绷!) 王者荣耀边境突围和五军对决模式的具体玩…

全局页面数据渲染--SAAS本地化及未来之窗行业应用跨平台架构

一、代码 /* 未来之窗通用数据渲染// 定义了一个名为"未来之窗_人工智能_前端口_数据渲染到界面"的函数 function 未来之窗_人工智能_前端口_数据渲染到界面(obj, 前置参数) {// 开启一个控制台分组,用于组织相关的输出信息console.group("未来之窗…

MySQL集群的基础部署及主从复制详解

一、Msql在服务器中的部署方法 官网:http://www.mysql.com 在企业中90%的服务器操作系统均为Linux 在企业中对于Mysql的安装通常用源码编译的方式来进行 1.1 在Linux下部署MySQL 1.1.1 部署环境 主机IP角色MySQL-node1172.25.254.13masterMySQL-node2172.25.…

Linux--IO模型_多路转接

目录 0.往期文章 1.五种IO模型介绍 概念 调用函数(非阻塞IO) 2.详解多路转接 之select select函数介绍 设置文件描述符 写一个基于select的TCP服务器 辅助库 基于TCP的Socket封装 服务器代码 测试服务器 小结 3.详解多路转接 之poll poll函…

基于OpenCV+MFC的KCF测速软件

基于OpenCVMFC的KCF测速软件 引言原理介绍使用介绍(1)主界面(2)打开视频(3)点击KCF测速(4)框选待检测目标(5)测速结果 资源链接(包含源码&#xf…

SpringMVC处理流程介绍

SpringMVC请求处理流程 发起请求到前端控制器(DispatcherServlet)前端控制器请求HandlerMapping查找Handler(可以根据xml配置,注解进行查找) 对应Spring源码 //在类DispatcherServlet里面 protected void doDispatch(HttpServletRequest request, HttpServletResponse respon…

static关键字与单例模式

可以修饰属性变量,方法和代码段 static修饰的属性称为静态属性或类属性, 在类加载时就在方法区为属性开辟存储空间,无论创建多少个对象,静态属性在内存中只有一份。 可以使用 类名.静态属性 的方式引用 static修饰的方法称为静态…

FPGA第 5 篇,FPGA技术优略势,FPGA学习方向,FPGA学习路线(FPGA专业知识的学习方向,FPGA现场可编程门阵列学习路线和方向)

前言 前几篇讲了一下FPGA的发展和应用,以及未来前景。具体详细,请看 FPGA发展和应用,以及未来前景https://blog.csdn.net/weixin_65793170/category_12665249.html 这里我们来,记录一下,FPGA专业知识的学习路线 一.…

第22周:调用Gensim库训练Word2Vec模型

目录 前言 一、Word2vec基本知识 1.1 Word2Vec是什么 1.2 Word2Vec两种主要模型架构 1.2.1 CBOW模型 1.2.2 Skip-gram模型 1.3 实例说明 1.4 调用方法 二、准备工作 2.1 安装Gensim库 2.2 对原始语料分词 2.2 添加自定义停用词 三、训练Word2Vec模型 四、模型应用…

快速掌握GPTEngineer:用AI创建网页应用的实用教程

今天来聊聊一个非常有趣的工具——GPTEngineer。这是一个基于AI的网页开发平台,特别适合那些不熟悉编程但又想快速创建网页应用的人。如果你想用简单的文本描述来生成一个网站或者应用,GPTEngineer可能就是你需要的。我们一步步看看如何使用它。 1. 了解…

Spring Boot 入门

1.1.1 什么是Spring Boot Spring Boot是一个开源的Java应用框架,由Pivotal团队提供,旨在简化Spring应用的初始搭建以及开发过程。‌ Spring Boot通过使用特定的配置方式,使得开发人员不再需要定义样板化的配置,从而在快速应用开发…

中仕公考:公务员考试缺考有影响吗?

公务员考试缺考的影响根据考试阶段的不同又所区别,中仕为大家介绍一下: 笔试阶段的缺考后果: 在公务员考试中,若考生未能按时参加笔试,将自动视为放弃该次考试机会。此行为不会对考生的个人信用产生任何负面效应&…

Win10 安装 Rabbitmq

参考文档:https://www.rabbitmq.com/docs/install-windows 一、安装 Erlang 语言 安装 RabbitMQ 需要该语言的支持才能安装 下载地址:https://erlang.org/download/otp_versions_tree.html 点击这里下载最新版本:27.0.1 直接默认 next 更…

【计算机网络】计算机网络的性能指标

1B/s 8bps ,MB/s 8Mbps 信道(Channel):表示向某一方向传送信息的通道(信道≠通信线路),一条通信线路在逻辑上往往对应一条发送信道和一条接收信道。

数盟IOS端可信ID

一、基本情况介绍 数盟IOS端可信ID介绍页: 数字联盟 数盟号称是还原出原生的IDFA, 但是苹果官网这么介绍: 用户开启跟踪允许跟踪后,APP才可以请求获取IDFA,且用户交互界面允许后,APP才能获取到IDFA. 官网给出的基本架构&#xf…

Linux基础1-基本指令7(其他常用指令,shell简介)

目录 1.uname 2.常用小指令 3.查看系统信息的其他指令 4.shell命令及其原理 4.1这里我们简单了解一下shell 4.2 shell存在的意义? 1.uname 如何查看计算机体系架构? uname -a,查看详细信息 uname -r 查看简要信息 2.常用小指令 TAB&#x…

el-table自定义合并表格

前沿 : 为了更好的展示数据,很多地方用到表格合并,但是element文档里面没有好的合并方法,只能自定义合并表格来解决需求。于是乎,写了以下方法,方面以后拿来即用。 自定义合并表格 表格数据 tableData: [{i…

laravel8快速开发简单博客系统(二)

目录 一、创建文章增删改成提交的控制器 1、注释文章查看权限,非登录状态可以查看文章列表页 2、创建提交控制器post 3、创建数据表 4、创建提交post资源路由 5、创建post控制器view目录post 二、文章添加功能实现 1.模板显示 2.复制home.blade.php模板到po…