策略模式-如何使用策略模式+工厂模式替换现有的if-else

1.定义

策略模式是一种行为设计模式, 它能让你定义一系列算法, 并将每种算法分别放入独立的类中, 以使算法的对象能够相互替换。

2.问题

一天, 你打算为游客们创建一款导游程序。 该程序的核心功能是提供美观的地图, 以帮助用户在任何城市中快速定位。

用户期待的程序新功能是自动路线规划: 他们希望输入地址后就能在地图上看到前往目的地的最快路线。

程序的首个版本只能规划公路路线。 驾车旅行的人们对此非常满意。 但很显然, 并非所有人都会在度假时开车。 因此你在下次更新时添加了规划步行路线的功能。 此后, 你又添加了规划公共交通路线的功能。

而这只是个开始。 不久后, 你又要为骑行者规划路线。 又过了一段时间, 你又要为游览城市中的所有景点规划路线。

尽管从商业角度来看, 这款应用非常成功, 但其技术部分却让你非常头疼: 每次添加新的路线规划算法后, 导游应用中主要类的体积就会增加一倍。 终于在某个时候, 你觉得自己没法继续维护这堆代码了。

无论是修复简单缺陷还是微调街道权重, 对某个算法进行任何修改都会影响整个类, 从而增加在已有正常运行代码中引入错误的风险。

此外, 团队合作将变得低效。 如果你在应用成功发布后招募了团队成员, 他们会抱怨在合并冲突的工作上花费了太多时间。 在实现新功能的过程中, 你的团队需要修改同一个巨大的类, 这样他们所编写的代码相互之间就可能会出现冲突。

3.代码示例

假如现在你有一个业务需求,针对四种不同的判断条件,需要选择执行不同的动作。就好比下面的代码

    public static void main(String[] args) {
        int i = (int) (Math.random()*4);
        System.out.println(i);

        if(i == 1){
            System.out.println(i*1);
        }else if(i == 2){
            System.out.println(i+1);
        }else if(i == 3){
            System.out.println(i-1);
        }else if(i == 4){
            System.out.println(i*10);
        }
    }

代码很简单,大家都可以看懂。那么如果我们要将上面的代码改造成为策略模式该怎么进行?

首先,我们依据策略模式的定义,定义中表名策略模式之间是可以进行互换的,那我们首先想到的就是使用接口。首先 我们定义策略模式的接口。代码如下:

public interface IReceiptHandleStrategy {
    void handle(int i);
}

然后依据我们上面的代码,分别写出对应的实现算法。

public class OneReceiptHandleStrategy implements IReceiptHandleStrategy{
    @Override
    public void handle(int i) {
        System.out.println(i*1);
    }
}
public class TwoReceiptHandleStrategy implements IReceiptHandleStrategy{
    @Override
    public void handle(int i) {
        System.out.println(i + 1);
    }
}
public class ThreeReceiptHandleStrategy implements IReceiptHandleStrategy{
    @Override
    public void handle(int i) {
        System.out.println(i - 1);
    }
}
public class FourReceiptHandleStrategy implements IReceiptHandleStrategy{
    @Override
    public void handle(int i) {
        System.out.println(i * 10);
    }
}

可以看到,我们的代码执行的都比较简单,就是相当于把上面的打印写到每一个实现类中。那么接下来,我们需要写一个容器,去封装下面具体的实现类。这个容器要能起到以下的作用,接受策略模式的接口,调用接口的实现方法。代码如下

public class ReceiptStrategyContext {
    private IReceiptHandleStrategy receiptHandleStrategy;

    public void setReceiptHandleStrategy(IReceiptHandleStrategy receiptHandleStrategy) {
        this.receiptHandleStrategy = receiptHandleStrategy;
    }

    public void handleReceipt(int i){
        if (receiptHandleStrategy != null) {
            receiptHandleStrategy.handle(i);
        }
    }
}

那么这些写完了,我们就要考虑如果依据条件去对应正确的实现类。我们很容易可以想到使用map。那么,我们使用简单工厂模式+map。很容易就可以想到下面的代码:

public class ReceiptHandleStrategyFactory {

    private static Map<Integer,IReceiptHandleStrategy> receiptHandleStrategyMap;

    static {
        receiptHandleStrategyMap = new HashMap<>();
        receiptHandleStrategyMap.put(1,new OneReceiptHandleStrategy());
        receiptHandleStrategyMap.put(2,new TwoReceiptHandleStrategy());
        receiptHandleStrategyMap.put(3,new ThreeReceiptHandleStrategy());
        receiptHandleStrategyMap.put(4,new FourReceiptHandleStrategy());
    }
    private ReceiptHandleStrategyFactory(){

    }

    public static IReceiptHandleStrategy getReceiptHandleStrategy(int i){
        return receiptHandleStrategyMap.get(i);
    }
}

可以看到,工厂模式里面,map的key值就是对应的判断条件。然后我们修改我们的业务代码

public class CelueFirst {
    public static void main(String[] args) {
        int i = (int) (Math.random()*4);
        System.out.println(i);
        ReceiptStrategyContext receiptStrategyContext = new ReceiptStrategyContext();
        receiptStrategyContext.setReceiptHandleStrategy(ReceiptHandleStrategyFactory.getReceiptHandleStrategy(i));
        receiptStrategyContext.handleReceipt(i);


        /*if(i == 1){
            System.out.println(i*1);
        }else if(i == 2){
            System.out.println(i+1);
        }else if(i == 3){
            System.out.println(i-1);
        }else if(i == 4){
            System.out.println(i*10);
        }*/
    }
}

看到这里大家应该可以看到策略模式的好处了,假如现在我需要再额外添加一个条件,之前的代码是在if-else中再添加一个分支,使用策略模式的话。我们就需要再写一个实现类,然后再工厂方法里添加一下就可以了。就是这么简单,而且符合开闭原则,如果需要新增,我们就不需要再去动业务的代码。

4.总结

但是有人可能会说了,我觉得一点也不简单,写那么多的类和接口,不麻烦吗?而且我们开发使用的都是Controller-Service-Dao三层 怎么可能新建那么多类?这问题问题的好,说的对。我们实际开发中,是不能使用策略模式替换if-else的 因为不值得。但是这并不代表我们开发中不使用策略模式。其中有一个人说的非常好。
在这里插入图片描述

我们只写业务代码确实不用考虑这些。但是如果涉及到一个全新的业务场景,我们在设计的时候,是可以考虑加入设计模式的。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值