研磨设计模式day11代理模式

目录

场景

代码实现

​编辑

解析

定义

代理模式调用示意图

代理模式的特点 

本质 

​编辑何时选用 


场景

我有一个订单类,包含订单数、用户名和商品名,有一个订单接口包含了对订单类的getter和setter

现在有一个需求,a创建的订单只能a修改,其他人无权修改

代码实现

定义OrderApi接口

package day10代理模式;public interface OrderApi {public String getProductName();void setProductName(String productName,String user);public String getOrderUser();public void setOrderUser(String orderUser,String user);public int getOrderNum();void setOrderNum(int orderNum,String user);
}

Order类,实现订单接口

package day10代理模式;public class Order implements OrderApi{private String productName;private int orderNum;private String orderUser;public Order(String productName, int orderNum, String orderUser) {this.productName = productName;this.orderNum = orderNum;this.orderUser = orderUser;}@Overridepublic String toString() {return "Order{" +"productName='" + productName + '\'' +", orderNum=" + orderNum +", orderUser='" + orderUser + '\'' +'}';}public void setOrderUser(String orderUser) {this.orderUser = orderUser;}public void setProductName(String productName) {this.productName = productName;}@Overridepublic int getOrderNum() {return orderNum;}@Overridepublic void setOrderNum(int orderNum,String user) {this.orderNum = orderNum;}@Overridepublic String getProductName() {return productName;}@Overridepublic void setProductName(String productName, String user) {this.productName = productName;}@Overridepublic String getOrderUser() {return this.orderUser;}@Overridepublic void setOrderUser(String orderUser, String user) {this.orderUser = orderUser;}
}

现在创建一个代理类

package day10代理模式.java中的代理类;import day10代理模式.Order;
import day10代理模式.OrderApi;import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.util.Arrays;/*** 使用java中的动态代理*/
public class DynamicProxy implements InvocationHandler {/*** 被代理的对象*/private OrderApi order = null;/*** 获取 绑定好代理和具体对象后的目标对象的 接口** @param order 具体的订单对象,相当于具体目标对象* @return 绑定好代理和具体对象后的目标对象的接口*/public OrderApi getProxyInterface(Order order) {// 设置被代理的对象,好方便invoke里面的操作this.order = order;// 把真正的订单对象和动态代理关联起来OrderApi orderApi = (OrderApi) Proxy.newProxyInstance(order.getClass().getClassLoader(), order.getClass().getInterfaces(), this);return orderApi;}/*** 实现invoke,在这个方法里面,具体判断当前是在调用什么方法,需要如何处理* @param proxy* @param method* @param args* @return* @throws Throwable*/@Overridepublic Object invoke(Object proxy, Method method, Object[] args) throws Throwable {//        System.out.println("用到的方法有什么"+method.getName());System.out.println("args有什么"+ Arrays.toString(args));if (method.getName().startsWith("set")) {System.out.println("进入setter方法了哟");// 如果不是创建人,那就不能修改if (order.getOrderUser() != null && order.getOrderUser().equals(args[1])) {// 可以操作return method.invoke(order,args);}else {
//                args[1] 表示第二个才是用户System.out.println("对不起, " + args[1] + ",您无权修改本订单中的数据");}}else if(method.getName().startsWith("to")){System.out.println("现在调用toString方法了哟");return method.invoke(order,args);}else {// 不是调用setter方法就继续执行return method.invoke(order,args);}return null;}}

Client

package day10代理模式;import day10代理模式.java中的代理类.DynamicProxy;public class Client {public static void main(String[] args) {// 1.张三先创建了一个订单Order order = new Order("设计模式", 100, "张三");// 2.创建一个动态代理DynamicProxy dynamicProxy = new DynamicProxy();// 3.将订单与动态代理关联起来OrderApi orderApi = dynamicProxy.getProxyInterface(order);//4.以下就需要使用被代理过的接口来操作了//4.1 李四想要来修改,那就会报错orderApi.setOrderNum(123,"李四");System.out.println("李四修改后的记录==>  "+orderApi);//4.2 张三修改orderApi.setOrderNum(123,"张三");System.out.println("张三修改后的记录==>  "+orderApi);}
}

解析

代理类首先是实现一个名为InvocationHandler的接口。需要持有被代理对象也就是OrderApi,然后通过一个对外提供的方法将代理与被代理绑定起来。实现invoke方法,这个方法就是为了判断订单接口中当前在使用的方法,对正在使用的方法做什么处理

一行一行解析就是首先判断方法名字是不是set开头的,如果是就看一下订单对象是否为空和这个方法传过来的值中的第1个下标对象是不是等于持有的对象,如果是就可以操作,如果不是就提示。

定义

 

代理模式调用示意图

代理模式的特点 

本质 

控制对象访问

何时选用 

 

 

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

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

相关文章

PDFPrinting.Net Crack

PDFPrinting.Net Crack 它能够轻松灵活地预测完美的打印结果以及用户文件的示例性显示。在.NET的PDF打印中,可以快速浏览最关键的元素。如果用户需要获得更详细的概述,那么他可以查看快速入门手册,甚至现有文档的详细概述参考。 在这种情况下…

Langchain-React范式调用API —— 大模型调用自定义工具

因为Langchain的代码也不是很复杂,因此 直接看代码会更好的学习。 一些说明,我已经放到了注释当中。 请各位看官享用。 代码样例 from langchain.agents import initialize_agent from langchain.llms import OpenAI from langchain.tools import Bas…

不能从真实机向VMware里直接拖文件怎么办

如果真实机的文件不能拖动到虚拟机里面有两种解决办法: 1.重启虚拟机 2.更新自己的vmtools工具,因为这个操作是由他来完成的。 在虚拟机-------更新vmtools里面

数仓--------简单了解

作者前言 🎂 ✨✨✨✨✨✨🍧🍧🍧🍧🍧🍧🍧🎂 ​🎂 作者介绍: 🎂🎂 🎂 🎉🎉&#x1f389…

Leetcode-每日一题【剑指 Offer 37. 序列化二叉树】

题目 请实现两个函数,分别用来序列化和反序列化二叉树。 你需要设计一个算法来实现二叉树的序列化与反序列化。这里不限定你的序列 / 反序列化算法执行逻辑,你只需要保证一个二叉树可以被序列化为一个字符串并且将这个字符串反序列化为原始的树结构。 …

Hadoop学习一(初识大数据)

目录 一 什么是大数据? 二 大数据特征 三 分布式计算 四 Hadoop是什么? 五 Hadoop发展及版本 六 为什么要使用Hadoop 七 Hadoop vs. RDBMS 八 Hadoop生态圈 九 Hadoop架构 一 什么是大数据? 大数据是指无法在一定时间内用常规软件工具对其内…

vscode 配置

vscode 配置 安装插件 Better C SyntaxC/CCMake、CMake Tools 、CMake Language SupportDoxygen Documentation GeneratorGit Graphhighlight-wordsPythonvscode-iconsClang-Format和clangdtyporahex editor .vscode 中的文件 在 VS Code 中,.vscode​ 文件夹是用于…

vue3 基础知识 (生命周期) 06

你好! 文章目录 一、生命周期二、生命周期过程三、组件的 v-model 一、生命周期 每个组件都可能从 创建、挂载、更新、卸载 等一系列的过程 在这个过程中的某一个阶段,用于可能会想要 添加一些属于自己的代码逻辑(比如组件创建完成后请求一些…

各种中间件的默认端口

面试时会忘记个别中间件端口 docker:2375 nacos:8848 redis:6379 rabbitMq: 5672(后台配置的端口)15672(web管理界面)账号:guest15674(web STOMP插件):通过WebSocket…

SpringBoot案例-配置文件-yml配置文件

配置格式 SpringBoot提供了多种属性配置方式 application.propertiesapplication.ymlapplication.yaml常见配置文件格式对比 XML&#xff08;臃肿&#xff09; <configuration><database><host>localhost</host><port>3306</port><use…

【springboot】WebScoket双向通信:

文章目录 一、介绍&#xff1a;二、案例&#xff1a;三、使用&#xff1a;【1】导入WebSocket的maven坐标【2】导入WebSocket服务端组件WebSocketServer&#xff0c;用于和客户端通信【3】导入配置类WebSocketConfiguration&#xff0c;注册WebSocket的服务端组件【4】导入定时…

裂缝检测,只依赖OPENCV,基于YOLO8S

裂缝检测&#xff0c;只依赖OPENCV&#xff0c;YOLOV8S 现在YOLOV8S训练目标非常方便&#xff0c;可以直接转换成ONNX让OPENCV调用&#xff0c;支持C/PYTHON&#xff0c;原理很简单&#xff0c;自己找博客&#xff0c;有兴趣相互交流

VUE3 --->vue-router4 获取路由对象与参数

#记录# 1. 创建路由实例由 createRouter 实现 2. 路由模式 history 模式使用 createWebHistory() hash 模式使用 createWebHashHistory() 地址栏带 # 参数是基础路径&#xff0c;默认/ 路由的基础地址是 vite.config.js中的 base 配置的值&#xff0c; 默认是 /…

Redis使用

环境配置 代码实现 Java public CoursePublish getCoursePublishCache(Long courseId){//查询缓存Object jsonObj redisTemplate.opsForValue().get("course:" courseId);if(jsonObj!null){String jsonString jsonObj.toString();System.out.println("从缓…

Redis之stream类型解读

目录 基本介绍 数据结构 消息 消费组 消费者 基本使用命令 概述 xadd 命令 xtrim 命令 xdel 命令 xlen 命令 xrange 命令 xread 命令 xgroup 命令 xreadgroup 命令 xack 命令 基本介绍 Redis stream&#xff08;流&#xff09;是一种数据结构&#xff0c;其…

基于React实现无限滚动的日历详细教程,附源码【手写日历教程第二篇】

前言 最常见的日历大部分都是滚动去加载更多的月份&#xff0c;而不是让用户手动点击按钮切换日历月份。滚动加载的交互方式对于用户而言是更加丝滑和舒适的&#xff0c;没有明显的操作割裂感。 那么现在需要做一个这样的无限滚动的日历&#xff0c;前端开发者应该如何去思考…

maven下载不了仓库地址为https的依赖jar,配置参数忽略ssl安全检查

问题原因 私服使用的https地址&#xff0c;然后安全证书过期的或没有&#xff0c;使用maven命令时&#xff0c;可以添加以下参数&#xff0c;忽略安全检查 mvn -Dmaven.wagon.http.ssl.insecuretrue -Dmaven.wagon.http.ssl.allowalltrue -Dmaven.wagon.http.ssl.ignore.vali…

前端面试:【网络协议与性能优化】HTTP/HTTPS、TCP/IP和WebSocket

嗨&#xff0c;亲爱的Web开发者&#xff01;在构建现代Web应用时&#xff0c;了解网络协议是优化性能和确保安全性的关键。本文将深入探讨HTTP/HTTPS、TCP/IP和WebSocket这三个网络协议&#xff0c;帮助你理解它们的作用以及如何优化Web应用的性能。 1. HTTP/HTTPS协议&#xf…

慕课网 Go工程师 第三周 package和gomodules章节

Go包的引入&#xff1a; 包名前面加匿名&#xff0c;只引入但不使用&#xff0c;如果对应包有init函数&#xff0c;会执行init函数&#xff08;初始化操作&#xff09; 包名前面加. 把这个包的结构体和方法导入当前包&#xff0c;慎用&#xff0c;你不知道当前包和被引入的包用…

数据库事务四大特性

事务的4大特性&#xff08;ACID&#xff09;&#xff1a; 原子性(Atomicity)&#xff1a; 事务是数据库的逻辑工作单位&#xff0c;它对数据库的修改要么全部执行&#xff0c;要么全部不执行。 一致性(Consistemcy)&#xff1a; 事务前后&#xff0c;数据库的状态都满足所有的完…