这样写代码,可以干掉 if...else...


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
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值