策略模式(Strategy Pattern)
一、概念
策略模式(Strategy Pattern)是当有多种算法且调用和返回方式相似的情况下,仅类型不同时,可以通过该模式将其封装起来,让它们之间可以互相替换。
策略模式可以用于改造代码中的if-else逻辑
二、适用场景
如果在一个系统里面有许多类,它们之间的区别仅在于它们的类型
,那么使用策略模式可以动态地让一个对象在许多类型中选择一种类型进行处理。 避免使用多重的if-else来实现
。
三、参与者
- 抽象策略角色(Abstract Strategy):通常为接口 或 抽象类,定义每个策略必须具有的方法和属性。
- 具体策略角色(Concrete Strategy):具体实现抽象策略中的接口,编写具体的业务逻辑
- 策略上下文角色/环境角色(Context Strategy): 该角色用于屏蔽高层模块对具体策略的直接访问,持有具体策略引用,将对具体策略的处理封装成对外api
- 用户(Client)
四、代码例子
假设我们要寄送一件快递到某一地点,快递打包好后有三种选择,标准快件、特快件、慢件,将这三种运送方式(Concrete Strategy)抽象出来作为实际策略对象,一个快件单(context)可以选择任意一种方式运送
抽象策略角色(Abstract Strategy):AbstractExpress
具体策略角色(Concrete Strategy):SlowExpress、StandardExpress、FastExpress
策略上下文角色/环境角色(Context Strategy): Parcel(快递单 Parcel)
五、UML图
六、优缺点
(一)优点
- 符合
开闭原则
- 可
避免使用多重条件语句
,如if—else语句、switch语句 - 可以提高算法的保密性和安全性
(二)缺点
- 调用端必须知道所有的策略,并且自行决定使用哪一个策略类
- 上层模块必须知道有哪些策略,然后才能决定使用哪一个策略,这与迪米特法则(最少知道原则)是相违背的,我只是想使用了一个策略,我凭什么就要了解这个策略呢?那要你的封装类还有什么意义?这是原装策略模式的一个缺点,幸运的是,我们可以使用其他模式来修正这个缺陷,如工厂方法模式、代理模式或享元模式。
- 代码中会产生非常多的策略类,增加了代码的维护难度。
- 如果系统中的一个策略家族的具体策略数量超过4个,则需要考虑使用混合模式,解决策略类膨胀和对外暴露的问题,否则日后的系统维护就会成为一个烫手山芋。
七、与其他模式比较
(一)策略模式与桥接模式的区别
- 桥接模式 属于结构型模式,
主要关注类和对象的组合
,而 策略模式 则属于行为模式,主要关注对象间的通信
。
-
- 桥接模式关注点:
当一个类内部具有2种及以上维度变化时,可以解耦这些维度
- 桥接模式关注点:
-
- 策略模式关注点:如果在一个系统里面有许多类,类的区别仅在于它们的类型不同,可以通过该模式
动态
的选择一种类型进行处理
- 策略模式关注点:如果在一个系统里面有许多类,类的区别仅在于它们的类型不同,可以通过该模式
-
在桥接模式中,
抽象实现角色(Abstraction)
通过聚合
方式引用具体实现角色(Implementor).
-
在策略模式中,
策略上下文角色(Context)
也通过聚合
引用具体实现策略(Strategy)
. - 这2种模式中,都存在
一个对象使用聚合的方式引用另一个对象的抽象接口的情况
,而且该抽象接口的实现可以有多种并且可以替换
。
-
- 两种模式都是让
调用者与被调用者之间的解耦,以及抽象接口与具体实现的分离
。
- 两种模式都是让
-
策略模式在解耦上还仅仅是某一个算法的层次,没有到
体系
这一层次。策略模式的结构是包含在桥接结构中的,“桥接模式中必然存在着策略模式 ”
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 全程不用写代码,我用AI程序员写了一个飞机大战
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 记一次.NET内存居高不下排查解决与启示
· DeepSeek 开源周回顾「GitHub 热点速览」
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了