位置: 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访京东多条件筛选教程(织梦系统)

  • 华为线下门店可以回收手机吗(华为线下门店可以退货吗)

    华为线下门店可以回收手机吗(华为线下门店可以退货吗)

  • 小米10如何开启热点(小米10如何开启开发者模式)

    小米10如何开启热点(小米10如何开启开发者模式)

  • 关闭修订有什么作用(关闭 修订)

    关闭修订有什么作用(关闭 修订)

  • ipad亮度突然自动变暗(ipad亮度突然自动变暗(ipad亮度突然变暗)怎么解决)

    ipad亮度突然自动变暗(ipad亮度突然自动变暗(ipad亮度突然变暗)怎么解决)

  • 微信加人频繁多久解封(微信加人频繁多久恢复)

    微信加人频繁多久解封(微信加人频繁多久恢复)

  • 华为平板和手机微信可以同步在线吗(华为平板和手机怎么同步)

    华为平板和手机微信可以同步在线吗(华为平板和手机怎么同步)

  • touchwiz主页已停止什么意思(touchwiz主页已停止反复出现)

    touchwiz主页已停止什么意思(touchwiz主页已停止反复出现)

  • 删掉的人怎么加回来(删掉的人怎么加回来不尴尬)

    删掉的人怎么加回来(删掉的人怎么加回来不尴尬)

  • 光猫百兆口和千兆口的区别(光猫百兆口和千兆口插哪个)

    光猫百兆口和千兆口的区别(光猫百兆口和千兆口插哪个)

  • iphonexr单手模式怎么开(xr单手操作)

    iphonexr单手模式怎么开(xr单手操作)

  • access数据库的结构层次(access数据库简介)

    access数据库的结构层次(access数据库简介)

  • 微信电影票能退吗(微信电影票退票流程)

    微信电影票能退吗(微信电影票退票流程)

  • 淘宝月卡为什么不是每个人有(淘宝月卡为什么用不了)

    淘宝月卡为什么不是每个人有(淘宝月卡为什么用不了)

  • 应用宝怎么解绑大王卡(应用宝怎么解绑qq)

    应用宝怎么解绑大王卡(应用宝怎么解绑qq)

  • 能不能在喜马拉雅看书(能不能在喜马拉雅听书)

    能不能在喜马拉雅看书(能不能在喜马拉雅听书)

  • iphone11怎么结束程序(苹果11怎么结束运行的程序)

    iphone11怎么结束程序(苹果11怎么结束运行的程序)

  • 怎么取消excel表格限制条件(怎么取消excel表的限制条件)

    怎么取消excel表格限制条件(怎么取消excel表的限制条件)

  • ipx4耳机能洗澡吗(耳机ipx4可以淋雨吗)

    ipx4耳机能洗澡吗(耳机ipx4可以淋雨吗)

  • 陌陌显示未知什么意思(陌陌上一些人显示的未知是什么意思)

    陌陌显示未知什么意思(陌陌上一些人显示的未知是什么意思)

  • 华为mate20pro防水功能(华为mate20pro的防水等级)

    华为mate20pro防水功能(华为mate20pro的防水等级)

  • 手机设置tp无线路由器怎么设置(手机设置tp无线连接)

    手机设置tp无线路由器怎么设置(手机设置tp无线连接)

  • mac系统电脑怎么静音? mac电脑静音的技巧(macbookzen)

    mac系统电脑怎么静音? mac电脑静音的技巧(macbookzen)

  • win10电源图标怎么隐藏(window10电源选项)

    win10电源图标怎么隐藏(window10电源选项)

  • 使用HBuilderX软件快速搭建Vue项目(hbuilderx的使用视频)

    使用HBuilderX软件快速搭建Vue项目(hbuilderx的使用视频)

  • 在Vue中获取DOM元素的实际宽高(在vue中获取dom元素)

    在Vue中获取DOM元素的实际宽高(在vue中获取dom元素)

  • 不确认递延所得税的特殊情况
  • 税盘连接服务器失败130008
  • 新办企业发票核定及申领,选否行吗
  • 工程材料票抵扣比例
  • 征税和补贴对市场结果的影响
  • 计提存货跌价准备怎么计算
  • 股东费用如何入账
  • 年末增值税结转账务处理流程
  • 做税审报告费如何做分录?
  • 国外客户给你寄来礼物怎么感谢
  • 新成立的公司银行存款如何入账
  • 用实物资产注资给子公司需缴纳增值税吗?
  • 石家庄国税发票查验平台
  • 资产相关的递延收益
  • 出纳如何审核报销发票
  • 可供出售金融资产发生减值会计处理
  • 去年亏损今年第一季度盈利
  • 小规模企业低值易耗品摊销方法
  • 账外资产评估入账固定资产折旧可以税前扣除吗?
  • 工地购买的零星材料计入什么科目
  • 收到汇算清缴的现金
  • 如何在excel中计算两列数值的差
  • linux如何使用
  • 简单制作教程
  • 股权转让协议解除返还股权优先权
  • 命令行wifi
  • 主板BIOS无法更改显存
  • win11专业版网卡安不了
  • 营改增会计分录
  • 什么是增值税进项税额和销项税额
  • 多台电脑共享打印机怎么设置
  • 一般纳税人差额征税申报表怎么填
  • 商业汇票计入什么科目技能高考
  • phpstrcmp函数
  • 运城盐湖中国死海养生城
  • php运算符号
  • pinf命令
  • php实现会话的步骤
  • 购入库存商品会计分录摘要
  • 收到事业单位分红怎么办
  • 每个季度30万免增值税
  • python有什么用
  • 智能手机登陆信息怎么删除
  • 设备购买与租赁的分析中,购买优于租赁的条件是
  • 小规模季报利润表的本月数怎么报
  • 库存现金的会计分录
  • 长期待摊费用核销
  • 民办非企业保险优惠政策
  • mysql密码忘了咋办
  • 委托加工应税消费品是指委托方提供原料和主要材料
  • 困难行业企业包括哪四大类
  • 长期待摊费用如何评估
  • 溢价发行债券取得的收益应如何处理
  • 业务招待费礼品要扣个税吗
  • 小规模30万含专票吗
  • 未分配利润高怎么解释
  • 限售股锁定期延长
  • 母公司与子公司的区别
  • 计提折旧的固定资产有哪些
  • 高新技术企业的税收优惠政策
  • 房地产开发企业增值税怎么算
  • 怎么禁止p2p下载器
  • macbook备份数据
  • windows8怎么设置
  • mac os 切换
  • 为避免10月20号后盗版系统出现黑屏的bat文件
  • win10取消uac
  • javascript冒泡排序代码
  • javascript ?
  • Cocos2dx3.2 Crazy Tetris update 定时更新 游戏逻辑处理
  • javascript弹窗函数
  • node_modules复制
  • Node.js中的事件循环是什么
  • relative absolute无法冲破的等级问题解决第1/3页
  • linux链接ln
  • unity2018.4破解
  • 各种手机ui大全
  • 国土国税垂管部主任是谁
  • 广东为什么用粤做简称?
  • 江苏盐在什么地方
  • 免责声明:网站部分图片文字素材来源于网络,如有侵权,请及时告知,我们会第一时间删除,谢谢! 邮箱:opceo@qq.com

    鄂ICP备2023003026号

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

    友情链接: 武汉网站建设