位置: IT常识 - 正文

设计模式---代理模式(设计模式代理模式)

编辑:rootadmin
简述 对客户端隐藏目标类,创建代理类拓展目标类,并且对于客户端隐藏功能拓展的细节,使得客户端可以像使用目标类一样使用代理类,面向代理(客户端只与代理类交互)。 话不多说,看一个优化案例。 优化案例 最初版v0 目前的功能是下载可以下载文件。 public class BiliBiliDownload ... 简述

推荐整理分享设计模式---代理模式(设计模式代理模式),希望有所帮助,仅作参考,欢迎阅读内容。

文章相关热门搜索词:设计代理完整版,设计模式代理模式的典型例子,设计模式代理模式的典型例子,设计模式代理模式的典型例子,设计模式代理模式的典型例子,设计模式代理模式 迭代器,设计模式代理模式,设计模式代理模式,内容如对您有帮助,希望把文章链接给更多的朋友!

对客户端隐藏目标类,创建代理类拓展目标类,并且对于客户端隐藏功能拓展的细节,使得客户端可以像使用目标类一样使用代理类,面向代理(客户端只与代理类交互)。

话不多说,看一个优化案例。

优化案例最初版v0

目前的功能是下载可以下载文件。

public class BiliBiliDownloader { public byte[] download(String filePath) throws InterruptedException { System.out.printf("正在下载BiliBili文件:%s%n", filePath); // 模拟文件下载,睡个10秒 Thread.sleep(10000); return new byte[1024]; // 假装是下载文件的字节数组 }}

客户端调用代码,如下。

public class Client { public static void main(String[] args) throws InterruptedException { BiliBiliDownloader bilidownloader = new BiliBiliDownloader(); bilidownloader.download("/root/buzuweiqi/java_manual.txt"); }}

下载工具类对客户端完全暴露,客户端可以直接使用下载类实现下载,这实际上是无可厚非的。经过研究发现,这个下载类有一个问题:每次调用都肯定会下载新的文件,即便文件已经被下载过。

为了解决这个问题,开发团队经过商讨已经有了一个初步的方案。看一下代码样例。

修改版v1

团队决定使用传统的修改方式(直接修改BiliBiliDownloader),认为这样最为的直观。确实,代码量少且未来可以预期修改不频繁时,传统的修改方案也未尝不是一个好的选择。

public class BiliBiliDownloader { // 定义用来缓存数据的map对象 private static Map<String, byte[]> map = new HashMap<>(); public byte[] download(String filePath) throws InterruptedException { System.out.printf("正在下载BiliBili文件:%s%n", filePath); if (map.containsKey(filePath)) { return map.get(filePath); } // 模拟文件下载,睡个10秒 Thread.sleep(10000); byte[] res = new byte[1024]; // 假装这是下载后的字节数组 map.put(filePath, res); // 加入缓存 return res; }}

客户端调用代码,还是和原来一样。

public class Client { public static void main(String[] args) throws IOException, InterruptedException { BiliBiliDownloader downloader = new BiliBiliDownloader(); downloader.download("/root/home/buzuweiqi/java_manual.txt"); // 由于文件已经缓存,所以这次下载非常快 downloader.download("/root/home/buzuweiqi/java_manual.txt"); // 由于文件还未缓存,所以这次下载比较缓慢 downloader.download("/root/home/buzuweiqi/linux_manual.txt"); }}设计模式---代理模式(设计模式代理模式)

到目前为止好像都没有啥不妥的地方。直到有一天,客户提出了新的需求:虽然现在只可以下载bilibili的文件(视频,音频,文章等),以后还想要下载youtube的文件。

为了实现这个需求,以及方便以后同类的需求变更,是时候用上代理模式。

修改版v2

代理模式在使用的时候需要顶一个一个顶层接口,并且使得代理类和被代理类都实现这个接口。代理类中需要持有非代理类的一个对象。并且在调用代理类的功能前后可以根据业务需要拓展新的功能。

public interface Downloader { byte[] download(String filePath) throws InterruptedException;}public class BiliBiliDownloader implements Downloader { public byte[] download(String filePath) throws InterruptedException { System.out.printf("正在下载BiliBili文件:%s%n", filePath); // 模拟文件下载,睡个10秒 Thread.sleep(10000); return new byte[1024]; // 假装是下载文件的字节数组 }}public class ProxyBiliBiliDownloader implements Downloader { private static Map<String, byte[]> map = new HashMap<>(); private BiliBiliDownloader downloader = new BiliBiliDownloader(); public byte[] download(String filePath) throws InterruptedException { if (map.containsKey(filePath)) { System.out.printf("正在下载BiliBili文件:%s%n", filePath); return map.get(filePath); } byte[] res = downloader.download(filePath); map.put(filePath, res); return res; }}public class YoutubeDownloader implements Downloader { public byte[] download(String filePath) throws InterruptedException { System.out.printf("正在下载Youtube文件:%s%n", filePath); // 模拟文件下载,睡个10秒 Thread.sleep(10000); return new byte[1024]; // 假装是下载文件的字节数组 }}public class ProxyYoutubeDownloader implements Downloader { private static Map<String, byte[]> map = new HashMap<>(); private BiliBiliDownloader downloader = new BiliBiliDownloader(); public byte[] download(String filePath) throws InterruptedException { if (map.containsKey(filePath)) { System.out.printf("正在下载Youtube文件:%s%n", filePath); return map.get(filePath); } byte[] res = downloader.download(filePath); map.put(filePath, res); return res; }}

客户端的使用案例如下。

public class Client { public static void main(String[] args) throws IOException, InterruptedException { Downloader downloader = new ProxyBiliBiliDownloader(); downloader.download("/root/home/buzuweiqi/java_manual.txt"); downloader = new ProxyYoutubeDownloader(); downloader.download("/root/home/buzuweiqi/linux_manual.txt"); }}

客户端不再依赖目标类,而是转而依赖代理类。代理模式使得增加相似需求时可以只增加一对实现类(目标类,代理类),而不用修改原本的类,符合开闭原则。

实际上通常我们会使用一个更为简单的方式控制代理对象的创建:反射。

修改版v3

高层接口,实现的目标类、代理类依旧不变。

public interface Downloader { byte[] download(String filePath) throws InterruptedException;}public class BiliBiliDownloader implements Downloader { public byte[] download(String filePath) throws InterruptedException { System.out.printf("正在下载BiliBili文件:%s%n", filePath); // 模拟文件下载,睡个10秒 Thread.sleep(10000); return new byte[1024]; // 假装是下载文件的字节数组 }}public class ProxyBiliBiliDownloader implements Downloader { private static Map<String, byte[]> map = new HashMap<>(); private BiliBiliDownloader downloader = new BiliBiliDownloader(); public byte[] download(String filePath) throws InterruptedException { if (map.containsKey(filePath)) { System.out.printf("正在下载BiliBili文件:%s%n", filePath); return map.get(filePath); } byte[] res = downloader.download(filePath); map.put(filePath, res); return res; }}public class YoutubeDownloader implements Downloader { public byte[] download(String filePath) throws InterruptedException { System.out.printf("正在下载Youtube文件:%s%n", filePath); // 模拟文件下载,睡个10秒 Thread.sleep(10000); return new byte[1024]; // 假装是下载文件的字节数组 }}public class ProxyYoutubeDownloader implements Downloader { private static Map<String, byte[]> map = new HashMap<>(); private BiliBiliDownloader downloader = new BiliBiliDownloader(); public byte[] download(String filePath) throws InterruptedException { if (map.containsKey(filePath)) { System.out.printf("正在下载Youtube文件:%s%n", filePath); return map.get(filePath); } byte[] res = downloader.download(filePath); map.put(filePath, res); return res; }}

在客户端调用时,引入Java反射,通过反射创建具体的代理对象。在config.prop文件中定义PROXY_NAME变量并指定需要反射创建的类的完整路径。

public class Client { public static void main(String[] args) throws Exception { Properties prop = new Properties(); prop.load(new FileReader("src/resource/props/config.prop")); Downloader downloader = (Downloader) Class.forName(prop.getProperty("PROXY_NAME")) .getDeclaredConstructor().newInstance(); downloader.download("/root/home/buzuweiqi/java_manual.txt"); downloader = new ProxyYoutubeDownloader(); downloader.download("/root/home/buzuweiqi/linux_manual.txt"); }}

通过Java反射机制,应对每次的需求变更,甚至都不需要修改客户端代码,只需要修改案例中的config.prop即可。减少了不必要的代码修改,提高了系统的可维护性。

总结优点

代理类与目标类的使用方式一致,这极大的降低了客户端调用的学习成本,易用性高。

面向接口,无需在意实现的细节。

缺点类的数量倍增,系统复杂度增加。适用场景当需要对于模块拓展,但又不方便打破客户端原有的调用规则时。客户端中对象的创建依旧需要修改,这没有什么好的办法。常用的代理模式使用方案缓冲代理(案例)远程代理虚拟代理

除此之外还有很多应用场景,代理模式是设计模式中使用非常广泛的一种。

本文链接地址:https://www.jiuchutong.com/zhishi/311549.html 转载请保留说明!

上一篇:自定义映射resultMap(映射器可以定义参数类型)

下一篇:织梦DedeCMS访京东多条件筛选教程(织梦系统)

  • 浅谈未来几种网赚的可行性!(未来网络发展趋势有哪些)

    浅谈未来几种网赚的可行性!(未来网络发展趋势有哪些)

  • 华为nova9怎么多机位拍摄(华为nova9怎么多开微信)

    华为nova9怎么多机位拍摄(华为nova9怎么多开微信)

  • win7设置密码(win7设置密码提示 密码不满足策略的要求)

    win7设置密码(win7设置密码提示 密码不满足策略的要求)

  • 华为荣耀v20有256g内存吗(华为荣耀v20有变声器吗)

    华为荣耀v20有256g内存吗(华为荣耀v20有变声器吗)

  • 错误代码503(错误代码50382-mw1)

    错误代码503(错误代码50382-mw1)

  • 视频过长怎么压缩发送(视频过长怎么压缩发送QQ)

    视频过长怎么压缩发送(视频过长怎么压缩发送QQ)

  • soul视频怎么去马赛克(soul视频怎么去掉头套)

    soul视频怎么去马赛克(soul视频怎么去掉头套)

  • qq留言板几年前的可以恢复吗(qq历史留言板)

    qq留言板几年前的可以恢复吗(qq历史留言板)

  • 微信在两个手机同时在线吗(微信在两个手机发起安全验证的间隔时间)

    微信在两个手机同时在线吗(微信在两个手机发起安全验证的间隔时间)

  • word和wps兼容吗(word跟wps兼容吗)

    word和wps兼容吗(word跟wps兼容吗)

  • WPS可以录屏吗(wps录屏功能能录声音吗)

    WPS可以录屏吗(wps录屏功能能录声音吗)

  • 抖音位置信息权限在哪里(抖音位置信息权限是干嘛滴)

    抖音位置信息权限在哪里(抖音位置信息权限是干嘛滴)

  • 快手移除粉丝怎么恢复(快手移除粉丝怎么拉回来)

    快手移除粉丝怎么恢复(快手移除粉丝怎么拉回来)

  • 微信需要横屏模式吗(微信横屏模式在哪里)

    微信需要横屏模式吗(微信横屏模式在哪里)

  • 手机怎么制作荧光字(手机怎么制作荧光棒视频)

    手机怎么制作荧光字(手机怎么制作荧光棒视频)

  • 快手私密作品怎么解除(快手私密作品怎么改音乐)

    快手私密作品怎么解除(快手私密作品怎么改音乐)

  • 键盘上end键的作用(键盘end键是哪个)

    键盘上end键的作用(键盘end键是哪个)

  • 手机wps怎么在方框里打钩(手机wps怎么在方块里打勾符号)

    手机wps怎么在方框里打钩(手机wps怎么在方块里打勾符号)

  • 浏览器工具栏隐藏怎么恢复(浏览器工具栏隐藏)

    浏览器工具栏隐藏怎么恢复(浏览器工具栏隐藏)

  • 趣步怎么使用(趣步怎么啦)

    趣步怎么使用(趣步怎么啦)

  • 怎么取消黑名单的手机号(怎么取消黑名单的人微信)

    怎么取消黑名单的手机号(怎么取消黑名单的人微信)

  • 英雄联盟中符文怎么设置?(英雄联盟符文推荐怎么不弹出来)

    英雄联盟中符文怎么设置?(英雄联盟符文推荐怎么不弹出来)

  • 华为鸿蒙开发官方解答:HarmonyOS Connect“碰一碰”出现问题怎么解决(华为鸿蒙系统开发平台)

    华为鸿蒙开发官方解答:HarmonyOS Connect“碰一碰”出现问题怎么解决(华为鸿蒙系统开发平台)

  • nvm安装(windows)(nvme安装win10教程)

    nvm安装(windows)(nvme安装win10教程)

  • apmd命令  进阶电源管理服务程序(apdl命令流手册下载)

    apmd命令 进阶电源管理服务程序(apdl命令流手册下载)

  • 什么情况下个人资产会被冻结
  • 旧机器设备出口
  • 用友会计报表
  • 民办非企业免税额度
  • 员工回家探亲的文案
  • 贴现利息应计入什么费用
  • 发票只能全部冲开吗
  • 现金流量表中购建固定资产怎么计算
  • 品牌对企业收益的影响
  • 加工皮革出口能申请退税吗
  • 房地产开发商转型
  • 进项税额可以在买东西吗
  • 股东多人实收资产怎么办
  • 应征消费税的汽车为啥不能抵扣
  • 公司之间转让股权,两家股东一样
  • 停车费要交税吗
  • 增值税进项税已转出后能否再抵扣
  • 小微企业企业税率表
  • 垃圾填埋沼气发电招聘
  • 专用发票右上角的数字表示什么
  • 财务费用年末有余额吗
  • mac系统怎么设置字体大小
  • 华为手机屏幕旋转设置
  • 部门预算编制方法
  • 什么叫毛利润和净利润
  • 土地补偿款会议记录范文
  • win11正式版问题
  • 苹果a1586是什么配置
  • bellzee.exe是什么
  • 怎么查发票的真假鉴定
  • 购买性支出和转移性支出都计入GDP
  • mcu version
  • 上市公司分红派股
  • 笑脸热气球 (© Leonsbox/Getty Images Plus)
  • php获取api内容
  • linux中web服务器的安装,配置与测试
  • 如何使用openAI总结小说内容
  • 这几个sql语法的区别
  • 记账凭证后面附发票吗
  • python多态的概念
  • python怎么写文字
  • mongodb快速入门
  • 银行回单应如何打印
  • 一般纳税人简易征收最新政策
  • 公司注册地址变更有什么影响
  • 经营成本包括五项内容
  • 发票使用范围指什么
  • 应税服务零税率是什么
  • 纳税人未抄报税怎么办
  • 商场预付卡
  • 补缴以前年度养老保险分录
  • 股东借款转增资本公积会计处理
  • 土地作为无形资产需要计提折旧吗?
  • 印花税征税对象包括
  • 未完工工程如何验收
  • 公司加班的餐费怎么算
  • 企业进口外汇额度限制
  • 个人独资企业要报税吗
  • mysql的自动增长怎么表示的?
  • sqlserver用户权限不给增删查改表结构权限
  • 迁移windows
  • windows映像文件位置
  • 出现闪退该怎么办
  • windows unistd.h
  • 怎么使用linux命令
  • cocos2dx ActionManager播放动画回调问题
  • js显示时间并且之后秒数实时更新
  • js实现登录界面
  • python输出代码怎么写
  • vim fold
  • python中字典的方法有哪些
  • angularjs常用总结
  • 从安卓设备导入
  • javascript基础编程
  • 云南省国家税务局
  • 深圳电子税务局税种启用在哪里
  • 对外支付税务备案表网上核验
  • 地税局下属单位
  • 个人股权转让是否增值了怎么判断
  • 柴油增值税发票
  • 免责声明:网站部分图片文字素材来源于网络,如有侵权,请及时告知,我们会第一时间删除,谢谢! 邮箱:opceo@qq.com

    鄂ICP备2023003026号

    网站地图: 企业信息 工商信息 财税知识 网络常识 编程技术

    友情链接: 武汉网站建设