行为模式聚焦对象间的交互与职责分配,通过封装算法和流程,让代码更灵活、易维护。本文带你快速掌握 10种核心行为模式的要点与应用场景,助你告别冗余代码!
核心要点:定义一系列算法,将每个算法封装成独立的策略类,使它们可以相互替换,让算法独立于使用它的客户端而变化。
关键作用:解耦算法与业务逻辑,避免在业务代码中出现大量复杂的条件判断逻辑,提高代码的可维护性和扩展性。
适用场景:当存在多种不同的算法来实现同一功能,且需要在运行时根据不同条件动态选择算法时,策略模式是不二之选。比如电商平台中的支付方式选择,有微信支付、支付宝支付、银行卡支付等多种策略;还有游戏中角色的攻击方式,可根据敌人类型切换近战、远程或魔法攻击策略。
核心要点:在抽象类中定义一个算法的骨架,把一些步骤的实现延迟到子类中。子类可以在不改变算法整体结构的情况下,重新定义某些步骤的具体实现。
关键作用:实现代码复用,将通用的流程和逻辑放在抽象类中,子类只需专注于实现差异化的部分,减少代码冗余。同时,方便对算法进行扩展和维护。
适用场景:适用于多个类具有相似的操作步骤,但某些步骤的实现细节不同的场景。像各种报表生成,都有数据查询、数据处理、报表展示等通用步骤,但不同报表的数据处理和展示方式各异;还有游戏中不同技能的释放流程,虽都包含技能准备、技能释放、技能效果等环节,但具体技能的效果实现不同 。
核心要点:定义了一种一对多的依赖关系,当一个对象(被观察者)的状态发生改变时,它会自动通知所有依赖它的对象(观察者)。
关键作用:实现对象之间的解耦,被观察者无需知道具体有哪些观察者,只负责状态变化时通知即可,观察者也只需关注自己感兴趣的状态变化,提高系统的灵活性和可扩展性。
适用场景:常用于需要实时同步状态或消息通知的场景。例如,股票交易系统中,当股票价格发生变化时,需要及时通知关注该股票的投资者;消息队列中,生产者发布消息后,消费者能及时收到消息并处理。
核心要点:将对象的状态封装成独立的状态类,对象的行为根据其当前状态来决定,状态的转换也由状态类来负责。
关键作用:避免使用庞大复杂的条件判断语句(如 switch - case 或 if - else 嵌套)来处理不同状态下的行为,使代码结构更清晰,可维护性更强。
适用场景:适用于对象的行为依赖于其内部状态,且状态变化频繁,不同状态下行为差异较大的场景。比如订单状态管理,从下单、支付、发货到收货,每个状态下订单的操作和响应不同;还有智能家电的状态控制,如空调的制冷、制热、关机等状态对应不同的行为逻辑。
核心要点:使多个对象都有机会处理请求,将这些对象连成一条链,请求在链上传递,直到有一个对象处理它为止。每个对象都可以决定是否处理请求以及是否将请求传递给下一个对象。
关键作用:解耦请求的发送者和接收者,发送者无需知道具体是哪个对象最终处理了请求,同时方便动态地组织和管理处理请求的对象链,提高系统的灵活性和可扩展性。
适用场景:常用于处理复杂的业务流程或请求审批流程。例如,请假审批流程,从员工提交请假申请,依次经过组长、部门经理、总经理等审批环节;还有日志处理系统,不同级别的日志可以由不同的处理器按顺序处理。
核心要点:将请求封装成一个命令对象,这个对象包含了执行请求所需的所有信息,如请求的接收者、执行的方法等。通过命令对象,可以对请求进行统一的管理和操作,支持撤销、重做等功能。
关键作用:解耦请求的发送者和接收者,发送者只需发送命令对象,无需关心具体的执行细节;同时方便实现操作的记录、回滚和批处理等功能,增强系统的可操作性和可维护性。
适用场景:适用于需要对操作进行记录、撤销、重做或批处理的场景。比如文本编辑器中的撤销和重做操作,游戏中的操作记录与回放功能,以及微服务架构中的命令调用。
核心要点:通过引入一个中介者对象,将原本相互耦合的多个对象之间的直接交互,转变为通过中介者进行间接交互。中介者负责封装对象之间的交互逻辑,管理对象之间的依赖关系。
关键作用:降低对象之间的耦合度,使系统的结构更加清晰,易于维护和扩展。当某个对象的行为发生变化时,只需修改中介者的逻辑,而不会影响到其他对象。
适用场景:适用于对象之间存在复杂网状依赖关系的场景。比如图形用户界面(GUI)中的组件交互,一个窗口中的多个按钮、文本框等组件之间的交互可以通过中介者来协调;还有电商订单系统中,订单对象与库存、支付、物流等多个服务之间的交互,可通过中介者进行统一管理。
核心要点:在不破坏对象封装性的前提下,捕获一个对象的内部状态,并将其保存起来,以便在将来某个时刻可以恢复到这个状态。
关键作用:实现对象状态的备份和恢复,为系统提供了一种历史版本回溯的能力,常用于需要支持撤销操作、版本控制或状态恢复的场景。
适用场景:例如,文本编辑器中的撤销操作,通过保存每次编辑前的状态,用户可以随时撤销到之前的版本;游戏中的存档功能,玩家可以保存当前游戏进度,在需要时恢复到存档时的状态;数据库备份与恢复,将数据库的某个时间点的状态保存为备份,以便在出现故障时恢复数据。
核心要点:提供一种方法顺序访问一个聚合对象中的各个元素,而又不暴露该对象的内部表示。将集合对象的遍历逻辑从集合类中分离出来,封装到迭代器对象中。
关键作用:使集合的遍历操作与集合的内部结构解耦,提供了统一的遍历接口,方便对不同类型的集合进行遍历操作,同时也支持正向、反向等多种遍历方式,提高代码的可维护性和可扩展性。
适用场景:适用于需要对各种集合(如列表、数组、树状结构等)进行遍历的场景。比如在开发中,对数据库查询结果集的遍历,对游戏场景中各种游戏对象集合的遍历。
核心要点:将数据结构和对数据的操作分离,定义一个访问者接口,其中包含对数据结构中各种元素的访问方法。通过访问者对象来执行对数据的操作,而不是在数据结构的类中直接实现这些操作。
关键作用:当需要对一个复杂的数据结构进行多种不同的操作时,使用访问者模式可以避免在数据结构类中添加大量的操作方法,使代码结构更清晰,易于维护和扩展。同时,方便在不修改数据结构类的前提下,动态地添加新的操作。
适用场景:适用于数据结构相对稳定,但操作经常变化的场景。比如电商系统中,对商品数据结构进行总价计算、库存统计、利润分析等多种操作;编译器设计中,对语法树的遍历和语义分析。
在实际开发中,如何快速选择合适的行为模式呢?这里为你准备了一份超实用的选型指南:
需求场景 | 推荐模式 |
---|---|
动态算法切换 | 策略模式 |
流程统一管理 | 模板方法模式 |
实时状态同步 | 观察者模式 |
状态驱动行为 | 状态模式 |
请求链式处理 | 责任链模式 |
操作记录与回滚 | 命令模式 / 备忘录模式 |
复杂对象交互 | 中介者模式 |
集合遍历 | 迭代器模式 |
多维度数据分析 | 访问者模式 |
行为模式是代码设计的 “软实力”,合理运用可显著提升代码的灵活性与可维护性。实际开发中,有以下几点建议:
优先选择简单模式:能用策略模式解决的条件判断问题,就不要用复杂的 if-else 嵌套,让代码更简洁、易读。
组合模式优化:将行为模式与其他模式(如工厂模式)结合使用。例如,在使用策略模式时,通过工厂模式来创建具体的策略对象,更方便管理对象的创建和生命周期。
性能监控:使用观察者模式时,要注意观察者数量过多可能导致的通知效率问题;在责任链模式中,需控制链的长度,避免请求处理时间过长影响性能。
你在项目中用过哪些行为模式?欢迎在评论区分享你的实践经验!
划重点:设计模式的本质是 “封装变化”,学会识别业务中的变化点是掌握模式的关键!