当前位置: 首页 > news >正文

【设计模式-12】代理模式的代码实现及使用场景

 代理模式是一种应用很广发的结构性设计模式,它的设计初衷就是通过引入新的代理对象,在客户端和目标对象之间起到中介的作用,从而实现控制客户端对目标对象的访问,比如增强或者阉割某些能力。

1. 概述

代理模式 给某一个对象提供一个代理,并由代理对象控制对原对象的引用,代理模式是一种结构性的设计模式。代理模式的结构比较简单,核心是代理类。

 代理模式的实现需要下面3个角色:

  • 抽象接口:声明的一个接口,保证被代理的对象和代理对象的类都可以实现抽象接口。
  • 被代理角色:真实的需要被代理的对象,也就是真正实现业务逻辑的角色。
  • 代理角色:代理模式的核心角色,代理类内部会对真实的被代理类进行引用,同时会增强或者删除某一些功能。

 代理模式常见的一般是静态代理和动态代理,由于静态代理只能与代理对象实现一对一的代理关系,容易造成类的急剧膨胀,所以从JDK1.3开始,Java提供了对动态代理的支持,下面我们先来看下动态代理的代码实现。


2. 代码实现

 我们下面通过JDK提供的reflect包的一些类来实现动态代理,假设有一个用户的信息user表,客户端可以通过用户信息的接口访问到用户的数据,我们来实现获取数据后,用户手机号脱敏以及日志记录,如下是日志服务查询用户手机号的逻辑实现。

  • 抽象接口
public interface UserInfo {/*** 获取用户手机号* @param passWord 用户密码* @return 用户手机号*/String getUserMobile(String passWord);
}
  • 被代理角色
public class LogRecord implements UserInfo {/*** 获取用户手机号* @param passWord 用户密码* @return 用户手机号*/@Overridepublic String getUserMobile(String passWord) {return "13521499999";}
}
  • 代理角色
public class UserInfoInvocationHandler implements InvocationHandler {private UserInfo userInfo;UserInfoInvocationHandler(UserInfo userInfo) {this.userInfo = userInfo;}@Overridepublic String invoke(Object proxy, Method method, Object[] args) throws Throwable {String userMobile = (String)method.invoke(userInfo, args);if (Objects.nonNull(userMobile)) {// 修改为userMobile = userMobile.substring(0, 3) + "****" + userMobile.substring(7, 11);}return userMobile;}
}
  • 客户端
public class Client {public static void main(String[] args) {UserInfo logRecord = new LogRecord();UserInfoInvocationHandler userInfoInvocationHandler = new UserInfoInvocationHandler(logRecord);// 获取代理对象UserInfo proxy = (UserInfo) Proxy.newProxyInstance(logRecord.getClass().getClassLoader(), new Class[] {UserInfo.class}, userInfoInvocationHandler);String userMobile = proxy.getUserMobile("123456");System.out.println(userMobile);}
}

3. UML类图

 下面,我们可以根据2中的代码案例,看一下类图:
在这里插入图片描述

4. 使用场景

 在真实的业务场景中,代理模式无处不在,比如我们跨实例的RPC调用,借助了远程代理的实现;对一些占用系统资源比较多或者加载时间较长的对象,可以通过虚拟代理来实现性能的提升。

 在很多框架中,都大量的使用了代理的概念,比如最典型的Spring的面向切面技术AOP,正是由于AOP的存在,我们使用代理的方式简化了很多,比如通过 @Aspect就可以实现对目标对象的代理,但是原理是一样的,包括底层实现也都是借助于动态代理的思想。

5. 总结

 代理模式和装饰器模式在代码实现上很类似,但是代理模式主要是给真实对象增加一些全新的职责,比如权限控制、缓存、日志等等,这些增加的职责与实际的业务逻辑实际上属于不同的业务域。而装饰器模式则是通过装饰类给具体的构建类增加一些相似的职责,是对原有职责的扩展,功能的增强,这些职责是属于一个问题域。

 而且,代理模式和装饰模式的目的也不相同,前者是实现对对象的控制访问,而后者是为了给对象增加、扩展某些功能。

相关文章:

  • 【SpringBoot】94、SpringBoot中使用MyBatis-Plus实现数据权限管理
  • 上海交通大学、中科大 开源镜像站停止 Docker Hub 仓库镜像支持后的可用替代源
  • springboot宠物领养系统-计算机毕业设计源码07863
  • python2.7pip报错:UnicodeDecodeError: ‘ascii‘ codec can‘t decode
  • 运维监控系统
  • 大数据安全经典面试题及回答(上)
  • 2024 年最新 windows 操作系统部署安装 redis 数据库详细教程(更新中)
  • 第二十一篇——信道:信息通道的容量有边界嘛?
  • 成员变量和for循环里面的变量不冲突原因
  • Java 桥接模式(Bridge Pattern)是设计模式中的一种结构型设计模式,桥接模式的核心思想是将抽象与实现解耦
  • 坚持刷题|合并有序链表
  • QT 中文乱码 以及 tr 的使用
  • 安徽京准-NTP网络授时服务器助力助力甘南州公共资源交易
  • QT 的文件
  • Linux网络编程:epoll
  • 网络传输文件的问题
  • [分享]iOS开发 - 实现UITableView Plain SectionView和table不停留一起滑动
  • 「面试题」如何实现一个圣杯布局?
  • 【跃迁之路】【519天】程序员高效学习方法论探索系列(实验阶段276-2018.07.09)...
  • css系列之关于字体的事
  • CSS中外联样式表代表的含义
  • download使用浅析
  • iOS | NSProxy
  • Java 9 被无情抛弃,Java 8 直接升级到 Java 10!!
  • Javascripit类型转换比较那点事儿,双等号(==)
  • JavaScript设计模式与开发实践系列之策略模式
  • javascript数组去重/查找/插入/删除
  • java小心机(3)| 浅析finalize()
  • PhantomJS 安装
  • ViewService——一种保证客户端与服务端同步的方法
  • vue的全局变量和全局拦截请求器
  • 半理解系列--Promise的进化史
  • 关键词挖掘技术哪家强(一)基于node.js技术开发一个关键字查询工具
  • 全栈开发——Linux
  • 数据库写操作弃用“SELECT ... FOR UPDATE”解决方案
  • 带你开发类似Pokemon Go的AR游戏
  • ​埃文科技受邀出席2024 “数据要素×”生态大会​
  • ​如何防止网络攻击?
  • #Datawhale AI夏令营第4期#多模态大模型复盘
  • #define与typedef区别
  • #gStore-weekly | gStore最新版本1.0之三角形计数函数的使用
  • (02)Cartographer源码无死角解析-(03) 新数据运行与地图保存、加载地图启动仅定位模式
  • (14)目标检测_SSD训练代码基于pytorch搭建代码
  • (8)Linux使用C语言读取proc/stat等cpu使用数据
  • (初研) Sentence-embedding fine-tune notebook
  • (附源码)spring boot公选课在线选课系统 毕业设计 142011
  • (附源码)springboot炼糖厂地磅全自动控制系统 毕业设计 341357
  • (附源码)计算机毕业设计SSM疫情社区管理系统
  • (十一)c52学习之旅-动态数码管
  • (转)大道至简,职场上做人做事做管理
  • (转)关于多人操作数据的处理策略
  • .bat批处理(八):各种形式的变量%0、%i、%%i、var、%var%、!var!的含义和区别
  • .NET Core 项目指定SDK版本
  • .NET Core使用NPOI导出复杂,美观的Excel详解
  • .Net 高效开发之不可错过的实用工具