0 概述
-
我在真实的业务开发场景中,有一个业务功能是:需要适配多个不同模板进行提取操作,我第一时间就想到可以使用策略模式,下面我就对策略模式进行一个讲解及使用举例
-
策略模式(Strategy Pattern)是一种行为设计模式,它允许在运行时动态地更改对象的行为。在策略模式中,一个类的行为或其算法可以在运行时更改。这种类型的设计模式属于行为模式。
-
策略模式定义了一系列的算法,并将每一个算法封装起来,使它们可以互相替换。策略模式使得算法可以独立于使用它的客户端。
-
组成部分:
- Strategy(策略):这是一个接口或抽象类,定义了所有支持的算法的公共接口
- ConcreteStrategy(具体策略):实现了 Strategy 接口或抽象类的具体策略,并提供了具体的算法实现
- Context(上下文):用一个 ConcreteStrategy 对象来配置。维护一个对 Strategy 对象的引用,Context 使用 Strategy 接口来调用其包含的算法
1 使用场景
- 多种算法实现:当有多种算法可以实现相同的功能,并且需要根据上下文选择不同的算法时,可使用策略模式
- 算法需要频繁更改:如果算法需要频繁更改,使用策略模式可以使算法更改更加容易,无需修改上下文代码
- 避免多重条件语句:当代码中存在大量的 if…else… 用于选择不同的算法时,可以考虑使用策略模式来替代
- 需要动态切换行为:当对象的行为需要在运行时根据特定条件动态更改时,可以使用策略模式
2 优缺点
- 优点:
- 策略模式提供了多种算法实现方式,客户端可以根据需要选择或切换不同的策略
- 当需要增加新的策略时,只需要增加新的具体策略类,无需修改原有代码
- 替代多重条件语句(if-else 或 switch-case),使代码更加清晰、易维护
- 策略模式将策略与上下文解耦,客户端可以动态地更改策略,而无需更改上下文代码
- 缺点:
- 客户端需要知道所有可能的策略,如果策略数量过多,可能会导致客户端代码变得复杂
- 如果策略选择不当,可能会导致性能下降。比如在频繁切换策略的情况下,每次切换都需要创建和销毁策略对象,这可能会带来额外的开销
3 演示 demo
-
使用策略模式选择以什么交通方式出行,UML 类图如下:
-
创建策略接口或抽象类,我这里创建接口
/** * 出行策略 * @Author Jasper * @Time 2024/2/11 * @公众号:EzCoding */ public interface TravelStrategy { void travel(); }
-
实现具体的出行策略:火车、飞机、汽车
/** * 具体策略-火车方式 * @Author Jasper * @Time 2024/2/11 * @公众号:EzCoding */ public class TrainStrategy implements TravelStrategy{ @Override public void travel() { System.out.println("我要坐火车"); } }
/** * 具体策略-飞机方式 * @Author Jasper * @Time 2024/2/11 * @公众号:EzCoding */ public class PlainStrategy implements TravelStrategy{ @Override public void travel() { System.out.println("我要坐飞机"); } }
/** * 具体策略-汽车方式 * @Author Jasper * @Time 2024/2/11 * @公众号:EzCoding */ public class CarStrategy implements TravelStrategy{ @Override public void travel() { System.out.println("我要坐汽车"); } }
-
创建 Context 上下文,维护对 strategy 对象的引用
/** * 上下文 * @Author Jasper * @Time 2024/2/11 * @公众号:EzCoding */ public class StrategyContext { private TravelStrategy travelStrategy; public StrategyContext(TravelStrategy travelStrategy) { this.travelStrategy = travelStrategy; } public void setTravelStrategy(TravelStrategy travelStrategy) { this.travelStrategy = travelStrategy; } public void doTravel() { travelStrategy.travel(); } }
-
测试类
/** * 测试类 * @Author Jasper * @Time 2024/2/11 * @公众号:EzCoding */ public class TravelTest { public static void main(String[] args) { // 火车 TrainStrategy trainStrategy = new TrainStrategy(); StrategyContext trainContext = new StrategyContext(trainStrategy); trainContext.doTravel(); // 输出:我要坐火车 // 飞机 PlainStrategy plainStrategy = new PlainStrategy(); StrategyContext plainContext = new StrategyContext(plainStrategy); plainContext.doTravel(); // 输出:我要坐飞机 // 汽车 CarStrategy carStrategy = new CarStrategy(); StrategyContext carContext = new StrategyContext(carStrategy); carContext.doTravel(); // 输出:我要坐汽车 } }
-
可以看到,StrategyContext 对象在执行出行方法时,并不关心具体使用的是哪种出行策略,他只是简单地调用TravelStrategy 接口中的 travel() 方法。这允许我们在不修改 StrategyContext 代码的情况下,增加新的出行策略或替换现有的策略,代码的可扩展性得到了很大的提高
- 以上就是策略模式的全部内容了,你们在工作中有用到策略模式吗,赶快收藏用起来
- 创作不易,感谢阅读,若您喜欢这篇文章,不妨传承这份知识的力量,点个赞或关注我吧~
- 微信公众号:EzCoding