一步步的利用设计模式优化存在大量if-else语句的代码

一般情况下,我们在写代码的时候,会根据传入的不同参数选择不同的处理方式,比如这样

public String eatLunch(String week) {
        String food = null;
        if ("Monday".equals(week)) {
            food = "肯德基";
        } else if ("Tuesday".equals(week)) {
            food = "麦当劳";
        } else if ("Wednesday".equals(week)) {
            food = "德克士";
        } else if ("Thursday".equals(week)) {
            food = "兰州拉面";
        } else if ("Friday".equals(week)) {
            food = "酸菜鱼";
        } else {
            food = "自己做";
        }
        return food;
    }

但是这样写的话会大大的增加代码的耦合性,着实不美

很多博客都说策略模式会解决这些if-else,但是我们在实际开发中,单纯的策略模式并不能消除if-else,只是进行了解耦和增加了可读性。要解决这个问题,可以用策略模式+简单工厂模式。

那么开始上代码

首先定义一个吃饭的策略接口类

public interface EatLunch {

    String getWeek();
    
    String ChoosingFood();

}

再写一个星期的枚举

public enum WeekEnum {

    MONDAY("Monday", "星期一"),
    TUESDAY("Tuesday", "星期二"),
    WEDNESDAY("Wednesday", "星期三"),
    THURSDAY("Thursday", "星期四"),
    FRIDAY("Friday", "星期五"),
    SATURDAY("Saturday", "星期六"),
    SUNDAY("Sunday", "星期天");

    public String code;
    public String name;

    WeekEnum(String code, String name) {
        this.code = code;
        this.name = name;
    }

    public String getCode() {
        return code;
    }

    public void setCode(String code) {
        this.code = code;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
}

然后是具体星期几的吃饭实现

星期一

public class MondayLunch implements EatLunch {
    @Override
    public String getWeek() {
        return WeekEnum.MONDAY.code;
    }

    @Override
    public String ChoosingFood() {
        System.out.println("吃肯德基");
        return "肯德基";
    }
}

星期二

public class TuesdayLunch implements EatLunch {
    @Override
    public String getWeek() {
        return WeekEnum.TUESDAY.code;
    }

    @Override
    public String ChoosingFood() {
        System.out.println("吃麦当劳");
        return "麦当劳";
    }
}

星期三

public class WednesdayLunch implements EatLunch {
    @Override
    public String getWeek() {
        return WeekEnum.WEDNESDAY.code;
    }

    @Override
    public String ChoosingFood() {
        System.out.println("吃德克士");
        return "德克士";
    }
}

其他的星期略。。。

然后我们构建一个策略工厂

public class StrategyFactory {

    public static EatLunch getLunch(String week) {
        EatLunch eatLunch = null;
        if (WeekEnum.MONDAY.code.equals(week)) {
            eatLunch = new MondayLunch();
        } else if (WeekEnum.TUESDAY.code.equals(week)) {
            eatLunch = new ThursdayLunch();
        } else if (WeekEnum.WEDNESDAY.code.equals(week)) {
            eatLunch = new WednesdayLunch();
        } else if (WeekEnum.THURSDAY.code.equals(week)) {
            eatLunch = new ThursdayLunch();
        } else if (WeekEnum.FRIDAY.code.equals(week)) {
            eatLunch = new FridayLunch();
        }
        return eatLunch;
    }

}

这样在客户端调用的时候,无论传的参数是什么,客户端都不会存在if-else了

但是又发现一个问题,策略工厂类里面还是有if-else啊,怎么把这里的也去掉呢?我们可以用Map容器来实现,这也是为什么上面的策略接口有一个看似没什么卵用的方法

String getWeek();

这个方法实际上是有用的

我们改造一下策略工厂类

public class StrategyFactory {

    private static Map<String, EatLunch> eatLunchMap = new ConcurrentHashMap<>();

    static {
        eatLunchMap.put(WeekEnum.MONDAY.code, new MondayLunch());
        eatLunchMap.put(WeekEnum.TUESDAY.code, new TuesdayLunch());
        eatLunchMap.put(WeekEnum.WEDNESDAY.code, new WednesdayLunch());
        eatLunchMap.put(WeekEnum.THURSDAY.code, new ThursdayLunch());
        eatLunchMap.put(WeekEnum.FRIDAY.code, new FridayLunch());
    }

    public static EatLunch getLunch(String week) {
        return eatLunchMap.get(week);
    }

}

这样就能够在策略工厂里也不出现if-else了

但是,你以为这样就结束了?No,No,No,这样写,虽然避免了if-else,但是随着策略的增多,策略工厂这个类也会修改,能不能不让它被修改?

在我们实际开发中,会用到Spring这个大杀器,所以最终版本

public class StrategyFactory implements ApplicationContextAware {

    private static Map<String, EatLunch> eatLunchMap = new ConcurrentHashMap<>();

    public static EatLunch getLunch(String week) {
        return eatLunchMap.get(week);
    }

    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        Map<String, EatLunch> map = applicationContext.getBeansOfType(EatLunch.class);
        map.forEach((key, value) -> eatLunchMap.put(value.getWeek(), value));
    }
}

这样,即使有新的策略,策略工厂也不需要修改,只需要重新写一个实现策略接口的类并在枚举类中加上具体的策略值就行了

  • 4
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值