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

  • pdf文件打开是网页(pdf文件打开是乱码)(PDF文件打开是网页怎么恢复)

    pdf文件打开是网页(pdf文件打开是乱码)(PDF文件打开是网页怎么恢复)

  • 剪映如何添加文字(剪映如何添加文字解说)

    剪映如何添加文字(剪映如何添加文字解说)

  • oppo手机nfc是什么功能(oppo手机nfc是什么意思)

    oppo手机nfc是什么功能(oppo手机nfc是什么意思)

  • 广电wifi已连接不可上网(广电已连接不可上网)

    广电wifi已连接不可上网(广电已连接不可上网)

  • 新注册微信身份证无法实名(新注册微信验证身份)

    新注册微信身份证无法实名(新注册微信验证身份)

  • 以太网电缆插口在哪(以太网电缆插口怎么插)

    以太网电缆插口在哪(以太网电缆插口怎么插)

  • 登录wifi的网址是多少(登陆wifi的网址)

    登录wifi的网址是多少(登陆wifi的网址)

  • 字里面带横线怎么整(字带横线怎么打出来)

    字里面带横线怎么整(字带横线怎么打出来)

  • 短信发送不出去是什么原因(联通短信发送不出去)

    短信发送不出去是什么原因(联通短信发送不出去)

  • iphonexs尺寸长宽厘米(iphonexs尺寸长宽高)

    iphonexs尺寸长宽厘米(iphonexs尺寸长宽高)

  • 华为小艺怎么按键唤醒(华为小艺怎样)

    华为小艺怎么按键唤醒(华为小艺怎样)

  • realmeQ怎么关闭应用通知(realme怎么关掉breeno)

    realmeQ怎么关闭应用通知(realme怎么关掉breeno)

  • 华为移动服务可以删除吗(华为移动服务可以强行停止吗)

    华为移动服务可以删除吗(华为移动服务可以强行停止吗)

  • word数字10竖着写(word里数字怎么竖着打)

    word数字10竖着写(word里数字怎么竖着打)

  • 台式电脑怎么连接wifi步骤(台式电脑怎么连接自己的无线网络)

    台式电脑怎么连接wifi步骤(台式电脑怎么连接自己的无线网络)

  • 微信有网抖音没网怎么回事(微信有网抖音没有网怎么回事)

    微信有网抖音没网怎么回事(微信有网抖音没有网怎么回事)

  • 计算机一级怎么算平均值(计算机一级怎么考才能过)

    计算机一级怎么算平均值(计算机一级怎么考才能过)

  • 网易云为什么苹果下载不了(iphonex网易云用不了)

    网易云为什么苹果下载不了(iphonex网易云用不了)

  • Photoshop如何绘制虚线曲线(photoshop如何绘制迷宫)

    Photoshop如何绘制虚线曲线(photoshop如何绘制迷宫)

  • oppo怎么解除耗资源高(oppo怎么解除耗电详细)

    oppo怎么解除耗资源高(oppo怎么解除耗电详细)

  • oppor11手机可以开空调吗(oppor11手机可以开空调吗?)

    oppor11手机可以开空调吗(oppor11手机可以开空调吗?)

  • 转转怎么注销(转转怎么注销账号?)

    转转怎么注销(转转怎么注销账号?)

  • 使用Word的技巧有哪些(word基本怎么使用)

    使用Word的技巧有哪些(word基本怎么使用)

  • 2022前端面试题汇总(持续更新中~)(2022前端面试题及答案)

    2022前端面试题汇总(持续更新中~)(2022前端面试题及答案)

  • 缴纳印花税的会计凭证
  • 应税和课税是什么意思
  • 税控是干什么用的
  • 专利年费滞纳金计入什么科目
  • 拍卖行业收取手续费标准
  • 行政单位利息收入可以扣除手续费
  • 虚增成本300万财务人员责任
  • 计提存货跌价准备是递延所得税资产吗
  • 异地预交所得税跨年还能用吗
  • 广告业与服务业哪个好
  • 退税降低
  • 财务软件要入固定资产吗
  • 一般纳税人旅游服务差额征税税率
  • 最新土地增值税筹划
  • 小微企业免征增值税条件
  • 保险公司赔偿计入营业外收入
  • 应交税费增加记借方还是贷方
  • 普通发票税收
  • 开户许可证复印件是什么
  • 小规模税局代增值税专用发票怎么交税
  • 汇算清缴时交的税怎么算
  • 工厂材料成本改善报告范文
  • 存货清查的步骤
  • 拆除原有建筑物成本扣除
  • WIN10显示缩略图
  • 其他现代服务包括哪些税目
  • 无形资产入股注意事项
  • 累计专项扣除比别人的多
  • win11测试版和正式版区别
  • 有销项无进项税务局会怎么罚
  • 【Fiddler Everywhere】史上最强抓包工具(安装 修改教程)
  • NJeeves.exe - NJeeves进程文件是什么意思 有什么用
  • php img
  • 出租设备的租金收入应计入什么科目
  • 收取职工交来伙食费如何入账
  • 三公经费包括哪些支出
  • 以前年度损益科目代码
  • openai发布时间
  • phpapi接口调用
  • 织梦数据库在哪
  • 代垫运费增值税计入销项税额吗
  • 企业实际发生的与取得收入有关的支出
  • 清单发票填开注意事项
  • 公司捐款怎样抵扣
  • 差额征税好吗
  • 预付账款购进原材料怎么做账
  • 处置固定资产增值税收入与企业所得税收入不一致
  • 职工社会保险费是什么意思
  • 资产负债表日后非调整事项应当在附注中披露
  • 固定资产核算的内容主要包括
  • 收到运输服务发票怎么做账务处理呢
  • 租房期间损坏应赔偿多少
  • 产品成本计算中最基本的方法是
  • 劳务公司发放农民工工资要交个税吗
  • 交通费用报销明细表
  • 当月增加的固定资产当月不计提折旧
  • 预期信用损失影响损益吗
  • nvidia发布了G6X
  • 电脑周边是什么
  • windows7窗口拖到屏幕顶端
  • linux,windows
  • centos7 zsh
  • win7安装软件提示停止工作
  • win7电脑视频预览图如何显示出来
  • linux 运行二进制文件
  • win7提示计算机内存不足
  • opengl 生成图片
  • ExtJS4 Grid改变单元格背景颜色及Column render学习
  • 幼儿园放鞭炮
  • node.js deno
  • 最流行的民宿装修设计
  • 批处理 读文件
  • 原生js实现promise
  • Android Studio cvs 状态颜色
  • 鼠标瞬间移动
  • 用javascript
  • 如何让listview提高效率
  • 湖北农信换手机登录不了
  • 亿企赢工作前景怎么样
  • 出口退税出现预缴怎么办
  • 免责声明:网站部分图片文字素材来源于网络,如有侵权,请及时告知,我们会第一时间删除,谢谢! 邮箱:opceo@qq.com

    鄂ICP备2023003026号

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

    友情链接: 武汉网站建设