据说是程序员工作中用到的最多的模式:策略模式解析

2024-03-19 06:18

本文主要是介绍据说是程序员工作中用到的最多的模式:策略模式解析,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

这是从零学习设计模式的第一篇文章,也算是入门篇吧。

大家都知道设计模式很重要,掌握设计模式是一个高级开发乃至架构师都必须要具备的技能。 但是不知道有没有这样的感觉,每次看设计模式的概念都差不多能看懂,但是就是不会用,而且不能够识别一些优秀的代码具体是运用了什么设计模式? 最终的结果就是,慢慢的忘记,脑海中的设计模式只是一个很大很虚的概念。

我目前就属于这种状态,为了能够提高自己的编码设计能力,在工作中设计出有弹性,好维护,能更好的应付业务变化的代码,准备认真学习一边设计模式。

其实大学期间就断断续续看过《Head First 设计模式》,但是当时印象也不深刻,工作后也不太会用。 到现在工作快四年了,再次看这本书,感觉真的不一样,也是因为工作这几年有了实战经验,慢慢知道了平时开发中的痛点,最后优化形成的解决方案,其实有很多就是用到了设计模式的思想。

目标

作为 Java 程序员,我们已经进入到对象村,OO思想和设计是已经深入人心的潜规则。 但是 良好的 OO 设计,并不是那么简单的,要结合前人大量的实践经验总结,不断的艰苦联系才能成功。 而这些前人的经验就是已经整理好的设计模式。

使用设计模式最好的方式是:“把模式装进脑子里,然后在你的设计和已有的应用中,寻找何处可以使用它们”。平时我们做的最多的是代码复用,而学习设计模式其实是经验复用。

一定要多回顾、多思考、多实践,这样才能深入理解和使用好设计模式。

入门:鸭子系统的设计

中级程序员的设计实现

我们来看一个简单的例子,鸭子系统的设计严谨,去理解设计模式带来的影响。

有一款模拟鸭子游戏,游戏中有很多种鸭子,会游泳,会呱呱叫,这时候利用 标准的 OO 技术,设计如下:

继承来实现

游泳和叫所有鸭子都会,所以为了代码复用,在基类中实现,外观由于各不相同是抽象方法,下沉到子类去实现,ok,符合 OO 思想,到此就结束了? 那只能说你太年轻。。

需求变更: 主管确定要求游戏中有会飞的鸭子,这时候你评估需求时,信誓旦旦的说,我们三天搞定。。。嗯。。加下班,明天就可以上线。

毕竟作为一名 OO 程序员,这没什么困难的,你直接在鸭子的基类中添加一个 fly() 方法,然后就被子类继承了, OO 大显神功。

但是,这个时候问题出现了,领导在测试环境做体验的时候,发现以前的 "僵尸鸭子" 居然也在天上飞来飞去,这下炸了,对代码局部的修改,居然影响到了全局,让一些没有生命力的鸭子也会飞上天了。

这个时候,你可能想到继承,可以在子类中覆盖父类的实现,将 “僵尸鸭子”的 fly() 非法覆盖掉,改为不会飞 。。。

这样虽然也可以,但是你要想到,如果后续又加入了 “诱饵鸭” 即不会飞也不会叫,这难道也要去其实现中重写对应的方法??

要知道作程序员,你一定要牢记一个不变的真理,那就是 CHANGE! 不管一开始设计的多么好,一段时间后,总是需要成长与改变。

到这里你也发现了,继承中的缺点是:

  1. 代码在多个子类中重复;
  2. 运行时的行为不容易改变,必须通过硬编码;
  3. 很难知道所有鸭子的全部行为,不同的子类实现不一样;
  4. 改一处就会动全身,造成子类鸭子不想要的改变;
把行为设计成接口

你可能会想到,将飞行行为和呱呱叫设计为对应的接口,有对应需要的鸭子直接去实现就好了,虽然这个方法是可以解决问题,但是你要想到,后续鸭子越来越多,每个都需要去实现飞行和呱呱叫接口,这样得要写多少重复的代码,无疑又掉入了另一个坑中。

模式大师来设计

找出应用中可能需要变化的,把它们独立出来进行封装

如果找到代码中可能需要变化的呢?

  1. 每次新需求来了,都会使某方面的代码发生变化,那么就可以确定,这部分代码需要被抽出来,和其他稳定的代码区分;
  2. 凭借自己对需求的理解,在一开始设计时将未来需求改变的代码抽出来封装;

这其实就是很多设计模式背后的精神所在,也是一种设计原则:“将会变化的部分取出来并封装起来,以便以后可以轻易地改动或扩充此部分,而不影响不需要变化的其他部分”。

所以,结合鸭子系统的需求,我们可以发现,鸭子的行为是经常变化的,因为有的会飞有的不会飞,有的会叫有的不会叫,所以需要抽出来进行封装。而其他部分还是比较正常的,所以依旧放到 Duck 基类中。

针对接口编程,而不是针对具体实现

上面我们已经知道了要将鸭子的 飞行和呱呱叫行为 抽出来封装,那么该如何实现呢?

我们的设计目标就是一切都有弹性,避免出现 中级开发工程师设计的系统,由于没有弹性所以才去请了模式大师出手。

大师将鸭子的行为设计成接口,如 FlyBehavior、QuackBehavior,这样行为就可以动态的扩展,我们可以在鸭子类中包含行为的方法,然后在 “运行时” 动态的 “改变” 飞行和呱呱叫行为。

也就是在,大师的设计中,鸭子的子类将使用接口(FlyBehavior 和 QuackBehavior)所表示的行为,所以实际的实现不会被绑死在鸭子的子类中。

而且我们也可以新增一些行为,不会影响到既有的飞行和呱呱叫行为,也不会影响 “使用”到已有行为的鸭子类,

多用组合,少用继承

相信这个概念你不是第一次听到了,组合优于继承,因为使用组合建立的系统拥有很大的弹性,可以“在运行时动态的改变行为”,因为结合上面的针对接口编程,只要组合的行为符合接口定义标准即可。

下面我们一起来看下,最终的系统结构:

认真去看下设计图,代码应该很好实现了,我就不写了。

设计模式:策略模式

上面大师的设计,就引出了我们今天要学习的设计模式:策略模式。不要怀疑,正是使用了策略模式改写了我们的鸭子系统。

策略模式定义了算法簇,分别分装起来,让它们之间可以互相转换,此模式让算法的变化独立于使用算法的客户。

思考与提升

  1. 我们如何使用设计模式?

我们开发中都是使用设计好的库和框架,这个没有问题,我们享受着别人代码的便利性,但是如何组装到我们的应用系统中,使我们的应用系统变得 易了解、容易维护、具有弹性,这个就需要设计模式出马了。但是设计模式不会直接进入你的代码中,你要做的就是先让设计模式进入你的大脑中,这样在开始新设计又或者当旧代码一团乱麻时,你就可以运用它们。

  1. 一开始想不到可用的设计模式?

这个是我们初学者必然遇到的问题,别慌,先牢记一些面向对象的原则,因为它们适用于所有模式,当我们踩过坑,不断思考这些原则最终的方案往往就是设计模式了。

OO基础:

  1. 抽象
  2. 封装
  3. 多态
  4. 继承

本文设计的OO原则(后续还有更多): 封装变化 多用组合,少用继承 针对接口编程,不针对实现编程

OO模式: 策略模式: 定义算法族,分别分装起来,让它们之间可以互相替换,此模式让算法的变化独立于使用算法的客户

更多精彩文章,可以关注我哦!
扫码关注

这篇关于据说是程序员工作中用到的最多的模式:策略模式解析的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/825061

相关文章

Deepseek使用指南与提问优化策略方式

《Deepseek使用指南与提问优化策略方式》本文介绍了DeepSeek语义搜索引擎的核心功能、集成方法及优化提问策略,通过自然语言处理和机器学习提供精准搜索结果,适用于智能客服、知识库检索等领域... 目录序言1. DeepSeek 概述2. DeepSeek 的集成与使用2.1 DeepSeek API

Redis的数据过期策略和数据淘汰策略

《Redis的数据过期策略和数据淘汰策略》本文主要介绍了Redis的数据过期策略和数据淘汰策略,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一... 目录一、数据过期策略1、惰性删除2、定期删除二、数据淘汰策略1、数据淘汰策略概念2、8种数据淘汰策略

Java实现状态模式的示例代码

《Java实现状态模式的示例代码》状态模式是一种行为型设计模式,允许对象根据其内部状态改变行为,本文主要介绍了Java实现状态模式的示例代码,文中通过示例代码介绍的非常详细,需要的朋友们下面随着小编来... 目录一、简介1、定义2、状态模式的结构二、Java实现案例1、电灯开关状态案例2、番茄工作法状态案例

C语言中自动与强制转换全解析

《C语言中自动与强制转换全解析》在编写C程序时,类型转换是确保数据正确性和一致性的关键环节,无论是隐式转换还是显式转换,都各有特点和应用场景,本文将详细探讨C语言中的类型转换机制,帮助您更好地理解并在... 目录类型转换的重要性自动类型转换(隐式转换)强制类型转换(显式转换)常见错误与注意事项总结与建议类型

SpringBoot中的404错误:原因、影响及解决策略

《SpringBoot中的404错误:原因、影响及解决策略》本文详细介绍了SpringBoot中404错误的出现原因、影响以及处理策略,404错误常见于URL路径错误、控制器配置问题、静态资源配置错误... 目录Spring Boot中的404错误:原因、影响及处理策略404错误的出现原因1. URL路径错

MySQL 缓存机制与架构解析(最新推荐)

《MySQL缓存机制与架构解析(最新推荐)》本文详细介绍了MySQL的缓存机制和整体架构,包括一级缓存(InnoDBBufferPool)和二级缓存(QueryCache),文章还探讨了SQL... 目录一、mysql缓存机制概述二、MySQL整体架构三、SQL查询执行全流程四、MySQL 8.0为何移除查

在Rust中要用Struct和Enum组织数据的原因解析

《在Rust中要用Struct和Enum组织数据的原因解析》在Rust中,Struct和Enum是组织数据的核心工具,Struct用于将相关字段封装为单一实体,便于管理和扩展,Enum用于明确定义所有... 目录为什么在Rust中要用Struct和Enum组织数据?一、使用struct组织数据:将相关字段绑

使用Java实现一个解析CURL脚本小工具

《使用Java实现一个解析CURL脚本小工具》文章介绍了如何使用Java实现一个解析CURL脚本的工具,该工具可以将CURL脚本中的Header解析为KVMap结构,获取URL路径、请求类型,解析UR... 目录使用示例实现原理具体实现CurlParserUtilCurlEntityICurlHandler

深入解析Spring TransactionTemplate 高级用法(示例代码)

《深入解析SpringTransactionTemplate高级用法(示例代码)》TransactionTemplate是Spring框架中一个强大的工具,它允许开发者以编程方式控制事务,通过... 目录1. TransactionTemplate 的核心概念2. 核心接口和类3. TransactionT

数据库使用之union、union all、各种join的用法区别解析

《数据库使用之union、unionall、各种join的用法区别解析》:本文主要介绍SQL中的Union和UnionAll的区别,包括去重与否以及使用时的注意事项,还详细解释了Join关键字,... 目录一、Union 和Union All1、区别:2、注意点:3、具体举例二、Join关键字的区别&php