设计模式之美
王争
前 Google 工程师,《数据结构与算法之美》专栏作者
123425 人已学习
新⼈⾸单¥98
登录后,你可以任选6讲全文学习
课程目录
已完结/共 113 讲
设计模式与范式:行为型 (18讲)
设计模式之美
15
15
1.0x
00:00/00:00
登录|注册

61 | 策略模式(下):如何实现一个支持给不同大小文件排序的小程序?

去掉代码中的if-else或者switch-case分支逻辑
项目开发中的策略模式应用
设计原则和思想
策略模式的作用
if-else分支判断
查表法
工厂模式
策略模式的第一步
拆分成独立的排序函数
代码复杂性
代码质量
sortFile()函数
MapReduce框架
多核优化
大文件排序问题
需求:实现对不同大小文件排序
设计原则和思想
设计意图和应用场景
移除if-else或者switch-case分支判断逻辑
原理和实现
课堂讨论
重点回顾
代码优化与重构
代码实现与分析
问题与解决思路
策略模式
如何实现一个支持给不同大小文件排序的小程序?

该思维导图由 AI 生成,仅供参考

上一节课,我们主要介绍了策略模式的原理和实现,以及如何利用策略模式来移除 if-else 或者 switch-case 分支判断逻辑。今天,我们结合“给文件排序”这样一个具体的例子,来详细讲一讲策略模式的设计意图和应用场景。
除此之外,在今天的讲解中,我还会通过一步一步地分析、重构,给你展示一个设计模式是如何“创造”出来的。通过今天的学习,你会发现,设计原则和思想其实比设计模式更加普适和重要,掌握了代码的设计原则和思想,我们甚至可以自己创造出来新的设计模式
话不多说,让我们正式开始今天的学习吧!

问题与解决思路

假设有这样一个需求,希望写一个小程序,实现对一个文件进行排序的功能。文件中只包含整型数,并且,相邻的数字通过逗号来区隔。如果由你来编写这样一个小程序,你会如何来实现呢?你可以把它当作面试题,先自己思考一下,再来看我下面的讲解。
你可能会说,这不是很简单嘛,只需要将文件中的内容读取出来,并且通过逗号分割成一个一个的数字,放到内存数组中,然后编写某种排序算法(比如快排),或者直接使用编程语言提供的排序函数,对数组进行排序,最后再将数组中的数据写入文件就可以了。
但是,如果文件很大呢?比如有 10GB 大小,因为内存有限(比如只有 8GB 大小),我们没办法一次性加载文件中的所有数据到内存中,这个时候,我们就要利用外部排序算法(具体怎么做,可以参看我的另一个专栏《数据结构与算法之美》中的“排序”相关章节)了。
确认放弃笔记?
放弃后所记笔记将不保留。
新功能上线,你的历史笔记已初始化为私密笔记,是否一键批量公开?
批量公开的笔记不会为你同步至部落
公开
同步至部落
取消
完成
0/2000
荧光笔
直线
曲线
笔记
复制
AI
  • 深入了解
  • 翻译
    • 英语
    • 中文简体
    • 中文繁体
    • 法语
    • 德语
    • 日语
    • 韩语
    • 俄语
    • 西班牙语
    • 阿拉伯语
  • 解释
  • 总结

本文详细介绍了如何利用策略模式实现一个支持不同大小文件排序的小程序。作者通过逐步分析和重构的方式,展示了从简单的排序算法到外部排序、多线程并发排序,再到MapReduce框架的应用,逐步展示了不同文件大小下的排序实现思路。在代码实现与分析部分,作者给出了一个Sorter类,并提出了代码设计上的优化建议,强调了设计原则和思想的重要性。通过多次重构,最终实现了符合策略模式的代码结构,让每一部分都不至于过于复杂、代码量过多。文章强调了设计原则和思想比设计模式更加普适和重要,指出掌握了代码的设计原则和思想,能更恰到好处地应用设计模式。整体而言,本文通过一个具体的例子,详细讲解了策略模式的设计意图和应用场景,对读者进行了技术上的启发和指导。

仅可试看部分内容,如需阅读全部内容,请付费购买文章所属专栏
《设计模式之美》
新⼈⾸单¥98
立即购买
登录 后留言

全部留言(102)

  • 最新
  • 精选
  • 永旭
    哪位了解无状态的类是什么意思 ?

    作者回复: 你可以简单理解为:只有函数,没有属性。

    2020-04-30
    3
    6
  • 一万小时
    策略模式看着像是个工厂模式

    作者回复: 目的不同

    2020-11-23
    3
  • Laughing
    在之前项目中,有个缓存的实现开始直接使用的redis来实现的,后来使用内存缓存替换,这样一来我使用了策略模式根据缓存key的类型,自动选择策略进行缓存。

    作者回复: 嗯嗯 ������

    2020-11-24
    1
  • Fitch Kuma
    对查表法来避免if-else很有感触,之前设计Jenkins pipeline是就是用Map来存放不同的component部署到不同server的映射关系的. 感觉策略模式的本质就是多态?

    作者回复: 嗯,用多态来实现的

    2020-07-05
    1
  • 木又寸
    策略类膨胀的情况,小争哥有没一些最佳实践可以分享? 业务实现上,可能一个父级策略下有多个子策略(譬如促销活动有满减/返现/立减等,满减规则下又有几种复杂的优惠策略),这时候把所有满减规则塞进一个策略类,有些偏离我们的初衷;将子策略拆分为独立的策略,策略类的数目又会急剧膨胀。 如何取舍?或者能否混合其他模式来适应这种场景?

    作者回复: 只保留满减、返现、立减等子策略,子子策略放到子策略中,不单独抽离出来实现,这样可以吗?

    2020-05-27
    3
    1
  • 吴小智
    "设计原则和思想比设计模式更加普适和重要",被这句话一下子点醒了。可以这样说,设计原则和思想是更高层次的理论和指导原则,设计模式只是这些理论和指导原则下,根据经验和场景,总结出来的编程范式。
    2020-03-23
    6
    215
  • 岁月
    看到这里我感觉好多设计模式都很类似, 都是先针对接口编程, 然后再加个查表法😂
    2020-04-02
    10
    77
  • 业余爱好者
    策略集合的信息也可以定义成枚举,可以放在数据库,可以放kv配置中心,等等。都是一样的道理。 策略模式是对策略的定义,创建和使用解藕。定义和创建的过程与业务逻辑关系不大,写在一起会影响可读性。 创建型模式是对创建和使用的解藕。 做什么和怎么做是应该解藕的,使用者并不关心具体的细节。 在业务逻辑中,与业务逻辑不大的代码应该放在外部。就像mvc的三层架构是业界的最佳实践。在service层调用dao层,而不是直接jdbc,因为如何操作数据库是个复杂的过程,却又与业务逻辑无关,所以单独抽出一层,代码结构变得更加清晰。 声明式编程很火。它就是把使用和内部实现原理解藕。java,spring的各种注解,声明式事务等等。使用者一个注解解决所有问题,无需关心底层。 业务逻辑无关的放在一起影响可读性,即使自己过一段时间看自己的代码也会迷惑。写代码要有用户思维,不光是提供的api满足kiss原则,内部的实现也是一样。能放在外面单位代码尽量怎么放在外面。只要能表达逻辑即可。
    2020-03-23
    1
    43
  • Jxin
    1.为了让调度的代码更优雅时使用。(就调度策略的代码而言,可读性高。理解结构后,阅读的心智负担低,因为调度的原理已经抽象成了共同的type查表,无需逐行检阅分支判断。像一些与持久数据相关的策略,有时为了兼容老数据或则平滑过度,无法全采用type查表,这时就需要结合if来 实现。所以采用if会让我误以为是这种场景,进而逐行检阅)。 2.感觉问反了,应该是什么场景下采用ifelse和witch。毕竟这两个的场景少些。答案是,在逻辑不复杂又不好用卫语句时采用。能用卫语句就不要ifelse。因为个人而言,看到retuern或conti能很明确跳出逻辑,else脑袋得转一下,当然这可能是个人习惯影响。但ifelse还是只在逻辑简单,没啥嵌套(一个函数内部不宜嵌套过多),且语义符合的场景用好些。 3.原则和思想毕竟是指导核心,是地图和尺子,自然是最重要的。但是不等于设计模式就比其不重要了。硬要说的话,我认为两个其实一样重要。设计模式是场景的积累,拉近了普通人与天才的差距,对我这种菜鸡来说可能比设计原则还重要。毕竟从设计原则到设计模式的出现,需要丰富经验,扎实知识和妙手偶得。如果没有设计模式的铺垫,普通人拿着设计模式的知识点要一路走上高质量代码的层级,实属不易。
    2020-03-23
    3
    25
  • 空白昵称
    很早前使用了类似策略模式的代码做了一个从各种渠道上传下载文件。(当时大学毕业,没看过策略模式,但是学过C++的多态)其实也就是基于接口而非实现编程思想。 if-else使用,如果判断较少,且未来几乎不会有新需求要再加一个else时,保持if-else即可。其他的都可以使用策略模式。不过本节demo的实例,使用range来匹配,目前看是没问题。但是如果需求变化,需要增加一个根据数据特征的动态分配排序算法,那么这里实现就麻烦了。所以需要根据具体需求来看使用什么模式...
    2020-03-24
    12
收起评论
显示
设置
留言
99+
收藏
沉浸
阅读
分享
手机端
快捷键
回顶部