日常 Coding 过程中,设计模式三板斧:模版、构建者、策略,今天来说下第三板斧 策略设计模式
策略模式还是比较简单并且使用较多的,平常我们多运用策略模式用来消除 if-else、switch 等多重判断的代码,消除 if-else、switch 多重判断 可以有效应对代码的复杂性,使设计解耦
如果分支判断会不断变化(增、删、改),那么可以使用技巧让策略模式满足开闭原则,提高代码的扩展性 (策略模式场景主要负责解耦,开闭原则需要额外支持)
下文中会详细列举如何使用设计模式做个 Demo 、模式的真实场景以及策略模式的好处
策略设计模式大纲如下:
- 什么是策略模式
- Spring 项目中真实的应用场景
- 框架源码底层如何玩耍策略模式
- 策略模式总结
策略模式在 GoF 的《设计模式》一书中,是这样定义的:
Define a family of algorithms, encapsulate each one, and make them interchangeable. Strategy lets the algorithm vary independently from clients that use it.
定义一组算法类,将每个算法分别封装起来,让它们可以互相替换。策略模式使这些算法在客户端调用它们的时候能够互不影响地变化,客户端代指使用算法的代码
看到上面的介绍可能不太明白策略模式具体为何物,这里会从最基本的代码说起,一步一步彻底掌握此模式。下述代码可能大家都能联想出对应的业务,根据对应的优惠类型,对价格作出相应的优惠
这段代码是能够满足项目中业务需求的,而且很多已上线生产环境的代码也有这类代码。但是,这一段代码存在存在两个弊端
如何运用策略模式优化上述代码,使程序设计看着简约、可扩展等特性
将上述代码块改造为策略设计模式,大致需要三个步骤
目前把抽象策略接口、具体的策略实现类以及策略工厂都已经创建了,现在可以看一下客户端需要如何调用,又是如何对客户端屏蔽具体实现细节的
根据代码块图片得知,具体策略类是从策略工厂中获取,确实是取消了 if-else 设计,在工厂中使用 Map 存储策略实现。获取到策略类后执行具体的优惠策略方法就可以获取优惠后的金额
通过分析大家得知,目前这种设计确实将应用代码的复杂性降低了。如果新增一个优惠策略,只需要新增一个策略算法实现类即可。但是,添加一个策略算法实现,意味着需要改动策略工厂中的代码,还是不符合开闭原则
如何完整实现符合开闭原则的策略模式,需要借助 Spring 的帮助,详细案例请继续往下看
最近项目中设计的一个功能用到了策略模式,分为两类角色,笔者负责定义抽象策略接口以及策略工厂,不同的策略算法需要各个业务方去实现,可以联想到上文中的优惠券功能。因为是 Spring 项目,所以都是按照 Spring 的方式进行处理,话不多说,上代码
可以看到,比对上面的示例代码,有两处明显的变化
小贴士:为了阅读方便,mark() 返回直接使用字符串替代,读者朋友在返回标示时最好使用枚举定义
接下来继续查看抽象策略工厂如何改造,才能满足开闭原则
和之前 [责任链模式] 相同,都是通过 InitializingBean 接口实现中调用 IOC 容器查找对应策略实现,随后将策略实现 mark() 方法返回值作为 key, 策略实现本身作为 value 添加到 Map 容器中等待客户端的调用
这里使用的 SpringBoot 测试类,注入策略工厂 Bean,通过策略工厂选择出具体的策略算法类,继而通过算法获取到优惠后的价格。小插曲:如果不想把策略工厂注入 Spring 也可以,实现方法有很多
总结下本小节,我们通过和 Spring 结合的方式,通过策略设计模式对文初的代码块进行了两块优化:应对代码的复杂性,让其满足开闭原则。更具体一些呢就是 通过抽象策略算法类减少代码的复杂性,继而通过 Spring 的一些特性同时满足了开闭原则,现在来了新需求只要添加新的策略类即可,健壮易扩展
自己用肯定觉得不够,必要时候还得看看设计开源框架源码的大佬们如何在代码中运用策略模式的
在作者了解中,JDK、Spring、SpringMvc、Mybatis、Dubbo 等等都运用了策略设计模式,这里就以 Mybatis 举例说明
Mybatis 中 Executor 代表执行器,负责增删改查的具体操作。其中用到了两种设计模式,模版方法以及策略模式
Executor 代表了抽象策略接口,刚才说到的模版方法模式源自 BaseExecutor
Configuration 代表策略工厂,负责创建具体的策略算法实现类
SimpleExecuto、ReuseExecutor... 表示封装了具体的策略算法实现类
上述代码块发生在 Configuration 类中创建执行器 Executor,通过 executorType 判断创建不同的策略算法。
上述代码块并没有彻底消除 if-else,因为 Mybatis 中执行器策略基本是固定的,也就是说它只会有这些 if-else 判断,基本不会新增或修改。如果非要消除 if-else,可以这么搞,这里写一下伪代码
这种方式叫做 "查表法",通过策略工厂实现消除 if-else 分支。最后,Mybatis 太过详细的设计这里不再赘述,有兴趣的小伙伴可以去把源码下载啃一啃
到了这里可能有读者看出了问题,策略模式就算消除了 if-else 但是如果添加新的策略类,不还是会违反开闭原则么?
没错,因为 Mybatis 本身没有引入 Spring 依赖,所以没有办法借助 IOC 容器实现开闭原则。Spring 是一种开闭原则解决方式,那还有没有别的解决方式?
解决方式有很多,开闭原则核心就是 对原有代码修改关闭,对新增代码开放。可以通过扫描指定包下的自定义注解亦或者通过 instanceof 判断是否继承自某接口都可以。不过, 项目如果用了 Spring 还是消停的吧
文章中图文并茂的方式介绍策略模式,通过价格优惠的场景,进而引用本文的重点:策略设计模式,相信小伙伴看完后都会有一定的收获
策略模式的本质依然是对代码设计解耦合,通过三类角色贯穿策略模式:抽象策略接口、策略工厂以及具体的策略实现类。通过细粒度的策略实现类避免了主体代码量过多,减少了设计中的复杂性。并通过开闭原则特性,添加新策略时可以保证最小、集中化修改代码
作者听到过很多小伙伴觉得自己做的都是 CRUD 工作,没有挑战性没意思。其实,我想说的是:业务代码一样牛逼,一样能体现程序员的水平。不一定非要高并发、大数据等场景。颇有一屋不扫何以扫天下的意思
最后抛出一个问题:出现 if-else 的代码,一定要使用策略模式优化么
如果 if-else 判断分支不多并且是固定的,后续不会出现新的分支,那我们完全 可以通过抽函数的方式降低程序复杂性;不要想法设法去除 if-else 语句,存在即合理。而且,使用策略模式会导致类增多,没有必要为了少量的判断分支引入策略模式
关于策略设计模式本文就讲到这里,后面会陆续输出工厂、原型、享元等模式
文章参考:《设计模式之美:策略模式》
本文由哈喽比特于3年以前收录,如有侵权请联系我们。
文章来源:https://mp.weixin.qq.com/s/MP3uq4gGxMlec_drA_7GJQ
京东创始人刘强东和其妻子章泽天最近成为了互联网舆论关注的焦点。有关他们“移民美国”和在美国购买豪宅的传言在互联网上广泛传播。然而,京东官方通过微博发言人发布的消息澄清了这些传言,称这些言论纯属虚假信息和蓄意捏造。
日前,据博主“@超能数码君老周”爆料,国内三大运营商中国移动、中国电信和中国联通预计将集体采购百万台规模的华为Mate60系列手机。
据报道,荷兰半导体设备公司ASML正看到美国对华遏制政策的负面影响。阿斯麦(ASML)CEO彼得·温宁克在一档电视节目中分享了他对中国大陆问题以及该公司面临的出口管制和保护主义的看法。彼得曾在多个场合表达了他对出口管制以及中荷经济关系的担忧。
今年早些时候,抖音悄然上线了一款名为“青桃”的 App,Slogan 为“看见你的热爱”,根据应用介绍可知,“青桃”是一个属于年轻人的兴趣知识视频平台,由抖音官方出品的中长视频关联版本,整体风格有些类似B站。
日前,威马汽车首席数据官梅松林转发了一份“世界各国地区拥车率排行榜”,同时,他发文表示:中国汽车普及率低于非洲国家尼日利亚,每百户家庭仅17户有车。意大利世界排名第一,每十户中九户有车。
近日,一项新的研究发现,维生素 C 和 E 等抗氧化剂会激活一种机制,刺激癌症肿瘤中新血管的生长,帮助它们生长和扩散。
据媒体援引消息人士报道,苹果公司正在测试使用3D打印技术来生产其智能手表的钢质底盘。消息传出后,3D系统一度大涨超10%,不过截至周三收盘,该股涨幅回落至2%以内。
9月2日,坐拥千万粉丝的网红主播“秀才”账号被封禁,在社交媒体平台上引发热议。平台相关负责人表示,“秀才”账号违反平台相关规定,已封禁。据知情人士透露,秀才近期被举报存在违法行为,这可能是他被封禁的部分原因。据悉,“秀才”年龄39岁,是安徽省亳州市蒙城县人,抖音网红,粉丝数量超1200万。他曾被称为“中老年...
9月3日消息,亚马逊的一些股东,包括持有该公司股票的一家养老基金,日前对亚马逊、其创始人贝索斯和其董事会提起诉讼,指控他们在为 Project Kuiper 卫星星座项目购买发射服务时“违反了信义义务”。
据消息,为推广自家应用,苹果现推出了一个名为“Apps by Apple”的网站,展示了苹果为旗下产品(如 iPhone、iPad、Apple Watch、Mac 和 Apple TV)开发的各种应用程序。
特斯拉本周在美国大幅下调Model S和X售价,引发了该公司一些最坚定支持者的不满。知名特斯拉多头、未来基金(Future Fund)管理合伙人加里·布莱克发帖称,降价是一种“短期麻醉剂”,会让潜在客户等待进一步降价。
据外媒9月2日报道,荷兰半导体设备制造商阿斯麦称,尽管荷兰政府颁布的半导体设备出口管制新规9月正式生效,但该公司已获得在2023年底以前向中国运送受限制芯片制造机器的许可。
近日,根据美国证券交易委员会的文件显示,苹果卫星服务提供商 Globalstar 近期向马斯克旗下的 SpaceX 支付 6400 万美元(约 4.65 亿元人民币)。用于在 2023-2025 年期间,发射卫星,进一步扩展苹果 iPhone 系列的 SOS 卫星服务。
据报道,马斯克旗下社交平台𝕏(推特)日前调整了隐私政策,允许 𝕏 使用用户发布的信息来训练其人工智能(AI)模型。新的隐私政策将于 9 月 29 日生效。新政策规定,𝕏可能会使用所收集到的平台信息和公开可用的信息,来帮助训练 𝕏 的机器学习或人工智能模型。
9月2日,荣耀CEO赵明在采访中谈及华为手机回归时表示,替老同事们高兴,觉得手机行业,由于华为的回归,让竞争充满了更多的可能性和更多的魅力,对行业来说也是件好事。
《自然》30日发表的一篇论文报道了一个名为Swift的人工智能(AI)系统,该系统驾驶无人机的能力可在真实世界中一对一冠军赛里战胜人类对手。
近日,非营利组织纽约真菌学会(NYMS)发出警告,表示亚马逊为代表的电商平台上,充斥着各种AI生成的蘑菇觅食科普书籍,其中存在诸多错误。
社交媒体平台𝕏(原推特)新隐私政策提到:“在您同意的情况下,我们可能出于安全、安保和身份识别目的收集和使用您的生物识别信息。”
2023年德国柏林消费电子展上,各大企业都带来了最新的理念和产品,而高端化、本土化的中国产品正在不断吸引欧洲等国际市场的目光。
罗永浩日前在直播中吐槽苹果即将推出的 iPhone 新品,具体内容为:“以我对我‘子公司’的了解,我认为 iPhone 15 跟 iPhone 14 不会有什么区别的,除了序(列)号变了,这个‘不要脸’的东西,这个‘臭厨子’。