环球今日报丨设计模式-用代理模式(Proxy Pattern)来拯救你的代码:打造可靠的程序设计
代理模式(ProxyPattern)是一种结构型设计模式,结构型模式描述如何将类或对象按某种布局组成更大的结构。它允许你提供一个代理对象来控制对
设计模式是一种高级编程技巧,也是一种通用的解决方案。它能在不同的应用场景中使用,它可以提高代码的可读性、可复用性和可维护性。设计模式的学习能提高我们的编程能力以及代码质量,同时也能提高我们的开发效率,减少代码的维护成本。
掌握设计模式对于开发软件而言是非常重要的,熟练地应用设计模式能让我们更加自信地去编写程序,另一方面,这也对我们的面试至关重要,这可是妥妥的加分项呢。所以为了我们的代码质量和未来发展而言,我们都要对设计模式有一定的了解和应用。
设计模式有23种,在一篇文章中全部讲完肯定是不可能的,这篇文章会先介绍 代理模式(Proxy Pattern)
,本文的代码示例用的是 Swift 语言编写。
【资料图】
代理模式(Proxy Pattern)代理模式(Proxy Pattern)是一种结构型设计模式,结构型模式描述如何将类或对象按某种布局组成更大的结构。它允许你提供一个代理对象来控制对另一个对象的访问。代理对象拥有与实际对象相同的接口,因此它可以被用来代替实际对象。
代理对象可以在调用实际对象之前或之后执行一些额外的操作,例如记录日志、缓存数据、控制访问权限等。这种模式通常被用于远程代理、虚拟代理(Virtual Proxy)、保护代理和延迟加载等应用场景。
代码示例代理模式(Proxy Pattern)通用类图代理模式:为其他对象提供一种代理以控制对这个对象的访问。最 初 的 定 义 出 现 于 《设 计 模 式 》 ( A d d i s o n - W e s l e y , 1 9 9 4 ) 。
Subject
主题接口,定义了真实主题和代理主题的公共接口,客户端可以通过主题接口来访问真实主题或者代理主题。RealSubject
真实主题,实现了主题接口,定义了真正的业务逻辑。Proxy
代理主题,也实现了主题接口,同时还持有了一个真实主题的引用,客户端通过代理主题来访问真实主题,代理主题可以对访问进行控制。以下是通用代码:
protocol Subject { func request()}class RealSubject: Subject { func request() { print("RealSubject handling request") }}class Proxy: Subject { private let realSubject = RealSubject() func request() { print("Proxy handling request") realSubject.request() }}
客户端调用代码:
let subject = Proxy()subject.request()
伪代码(老默,我想吃鱼了)突然想到了一个很有趣的例子,比如说我现在想吃鱼,那吃鱼得先去菜市场把鱼买回来吧,一般来说都是自己去菜市场里买鱼。但是我现在只想吃鱼而不想亲自去买鱼,那我就和代理人说一声,说我想吃鱼了,代理人就会代替我去菜市场把鱼带回来给我,亦或者是代理人找的别人去买也是可以的。伪代码如下所示:
protocol 主题接口 { func 去买鱼()}class 老默: 主题接口 { func 去买鱼() { print("把鱼买回来了") }}class 代理人: 主题接口 { private let 我是老默 = 老默() func 去买鱼() { 我是老默.去买鱼() }}
客户端调用的伪代码如下所示:
let 我是一个代理 = 代理类()我是一个代理.去买鱼()
每次想吃鱼我们就找到代理人,由它来安排,至于谁去我也不在乎。
虚拟代理(Virtual Proxy)我们拿虚拟代理(Virtual Proxy)来作为例子讲解说明,它是代理模式(Proxy Pattern)的一种,它在代理模式的应用中比较常见。
虚拟代理(Virtual Proxy)控制访问创建开销大的资源,其通过在代理对象和实际对象之间添加一层代理层,来实现对实际对象的延迟加载或缓存。
ImageLoader
定义一个协议,规定了代理对象和实际对象需要实现的方法。RealImageLoader
是遵循 ImageLoader
的实际对象,是实际做事的图片加载器。ImageLoaderProxy
是遵循 ImageLoader
的代理对象,它持有 RealImageLoader
的引用,并且还实现了一个简单的图片缓存机制,以避免重复下载相同的图片。我们首先编写 ImageLoader
协议,定义相同的接口方法:
protocol ImageLoader { func loadImage(url: URL, completion: @escaping (UIImage?) -> Void)}
接下来,编写图片加载器 RealImageLoader
类,并遵循 ImageLoader
协议:
class RealImageLoader: ImageLoader { func loadImage(url: URL, completion: @escaping (UIImage?) -> Void) { URLSession.shared.dataTask(with: url) { data, response, error in guard let data = data, error == nil else { completion(nil) return } let image = UIImage(data: data) completion(image) }.resume() }}
我们使用 URLSession
来执行一个异步的网络请求,将图片数据下载下来,并将其转换为 UIImage
对象并传递给回调闭包。
接下来,编写 ImageLoaderProxy
代理类:
class ImageLoaderProxy: ImageLoader { private let realImageLoader = RealImageLoader() private var cachedImages: [URL: UIImage] = [:] func loadImage(url: URL, completion: @escaping (UIImage?) -> Void) { if let cachedImage = cachedImages[url] { completion(cachedImage) } else { completion(UIImage(named: "image_loading_bg")) realImageLoader.loadImage(url: url) { [weak self] image in guard let self = self else { return } if let image = image { self.cachedImages[url] = image } completion(image) } } }}
当客户端调用 loadImage(url:completion:)
方法时,代理对象首先会判断是否已经缓存了对应的图片,如果已经缓存,则直接返回缓存的图片,否则先传递一个默认的加载图片用于显示过渡,再使用真正的图片加载器 RealImageLoader
加载图片,并在加载完成后缓存图片。
最后编写客户端的调用代码:
let imageLoader: ImageLoader = ImageLoaderProxy()if let url = URL(string: "https://img2.baidu.com/it/u=2082637540,462915030&fm=253&fmt=auto&app=138&f=JPEG?w=500&h=888") {imageLoader.loadImage(url: url) { [weak self] image inDispatchQueue.main.async {self?.imageView.image = image}}}
这里需要注意的是,imageLoader在网络请求的过程中不能被释放,否则闭包里的 self 会为空,你可以放在 controller 的属性当中。
DispatchQueue.main.async
方法使线程回到主线程执行图片的加载。
建议在开发者工具当中设置你的网络,将其设置为低速率的,这样方便我们查看效果。
总结代理模式(Proxy Pattern)允许你提供一个代理对象来控制对另一个对象的访问,隐藏具体的实现细节,一定程序上降低了系统的耦合度。可以起到保护目标对象的伤。可以对目标对象的功能增加,如本文介绍虚拟代理使用的图片加载例子,在其中加入了图片缓存就是这个形式。
当然它也是有缺点的,使用代理模式(Proxy Pattern)可能会使类的数量增加,也可能会增加代码的复杂度,因为它涉及到多个对象之间的协作。代理模式可能会导致有性能损失,因为客户端需要通过代理对象来访问真实对象,从而增加了额外的开销。
结语本文章的代码已经整理到 GitHub 上,请点击链接获取。
记得以前看过的一个新闻,有一句结尾的话印象挺深刻的,分享出来给大家:“时间过得真系快,又系时候讲拜拜”。话题转回来,我会定期发布一些技术文章,如果这篇文章对你有帮助,请你关注我。
关于作者博文作者:GarveyCalvin公众号:凡人程序猿本文版权归作者所有,欢迎转载,但必须保留此段声明,并给出原文链接,谢谢合作!
关键词:
代理模式(ProxyPattern)是一种结构型设计模式,结构型模式描述如何将类或对象按某种布局组成更大的结构。它允许你提供一个代理对象来控制对
超125亿元项目签约!中国数字经济产业发展大会在苏州相城举行,张桥,金融,研究院,苏州市,相城区,大运河,中国文物,新兴产业,中国世界遗产
1、仓库锁是用来保护用户仓库内物品安全的独立密码。玩家每次登陆游戏后第一次使用仓库(存放物品)时需要进行仓库密码验证;2、用户登录游戏后
2023年3月24日下午,全球动力电池龙头宁德时代(300750,股价393 58元,市值9613 2亿元)召开2022年业绩说明会。据证券日报报道,宁德时代董
迈克-布朗:没有福克斯的伤情更新但他一度想回来接着比赛,美国篮球,关键时刻,迈克-布朗,nba常规赛,德阿隆·福克斯
工厂指导价:269 8万元,保值率:59 38%。车身尺寸为333,605,230mm*1,871mm*1,48
第一:肌肉酸痛是一种正常的、积极的生理表现。人们往往在力量训练或一个不太适应的运动练习后,产生明显的肌肉酸痛和不适。肌肉酸痛分为急性
湖北最新人事任免
想必现在有很多小伙伴对于奥林匹克会旗图片方面的知识都比较想要了解,那么今天小好小编就为大家收集了一些关于奥林匹克会旗图片
1、北京西站地铁有:7号线、9号线。2、如果你去西四东大街,地铁都需要换乘。3、您可以出站后直接坐公交车3路或者特13路
1、用担,除登陆社保网查询(功能并非完善稳定)外通式查询:()社保局(二)拨打社保局服务电12333切记:查询需要
汉王科技发布的2022年年报显示,报告期内该公司营业总收入为14亿元,同比下降13 19%;营业亏损为1 74亿元,同比下降257 57%;利润总额为-1 74
《豪门焰》作者:晓春;《豪门焰续》作者:晓春;《冲撞》作者:晓春;《迟爱》作者:蓝淋;《龙游浅溪》作者:紫荆;《重生职业军人》作者:
首架!空客亚洲总装线总装A321飞机交付今日,记者从空客中国、吉祥航空获悉,空客今日交付了由位于天津的空客A320系列飞机亚洲总装线总装完成
3月23日,据安徽省蚌埠市住房公积金管理中心官网,为充分发挥住房公积金制度保障作用,支持合理住房需求,促进蚌埠市房地产市场平稳健康发展,
著名主持人春妮晒出与4岁儿子一起出海的照片,配文“因为有你,一切都值得”,配乐是《帅帅的小男孩》。这个萌娃是春妮与央视《新闻联播》主播
1、20集末 爱爱首次出场 倒挂在树上 21集开头 与佐助交换姓名 24 25集 笔试时用砂之眼作弊 爱爱超群的能力
【中汽协发起联合倡议:共同抵制汽车行业网络水军】24日,中新财经从中汽协获悉,为共同维护风清气正的网络舆论空间,营造公平、公正的汽车行
1、我好比一只小鸟,每根羽毛上有着您的深情抚爱和谆谆教导,让我在外面的天地间自由的飞翔,您的臂膀好比大树,永远是我温暖的家。妈妈,祝您
医疗板块继21日大涨后连续2日小幅盘整,资金再度开展逢低吸筹操作。行情数据显示,昨日(3月23日)医疗ETF(512170)获资金净申购超3200万元。