【设计模式实战】用三种设计模式去优化if-else屎山代码!!!

优化前提


前言

我们之前也学习了不少设计模式,今天给大家介绍一个案例,帮助大家更加熟悉设计模式,并能够在自己写项目的时候能够下意识的使用设计模式,避免写出屎山代码。🌈

提示:不清楚策略、工厂、模板方法模式的小伙伴可以参考上方文章。


一、 抛出屎山代码

我就以一个简单的代码模拟下业务,像我们平时写项目的时候,这种if-else语句非常常见,比如说:在判断支付类型的时候,在参数校验的时候等等。过多的if-else,会使代码冗余、可读性不好,最重要的是违反了“开闭原则”,拓展性非常的差,后面的同事看了后会非常的痛苦,内心一顿臭骂,为了避免被后面的同事吐槽谩骂,我们要写出更加优雅的代码。

void Example1(){
        String name = "小杰";
        if (name.equals("刘二")){
            System.out.println("刘二完成任务");
        } else if (name.equals("张三")) {
            System.out.println("张三完成任务");
        } else if (name.equals("李四")) {
            System.out.println("李四完成任务");
        } else if (name.equals("王五")) {
            System.out.println("王五完成任务");
        } else if (name.equals("赵六")) {
            System.out.println("赵六完成任务");
        } else if (name.equals("苏七")) {
            System.out.println("苏七完成任务");
        }
    }

二、如何解决

我们一步步引入设计模式,帮助大家理解

1.使用策略模式

分析代码

我们可以将if里面执行的代码可以看作一个个不同的策略,这样我们就可以引入策略模式去优化下面代码。

优化代码

首先,我们定义一个策略接口。

public interface Handler extends InitializingBean {
    void show();
}

实现具体的策略

public class LiSi implements Handler{
    //执行相应的策略
    @Override
    public void show() {
        System.out.println("李四完成了任务");
    }
    //这个方法是策略类初始化后需要执行的逻辑,这个我们先不管
    @Override
    public void afterPropertiesSet() throws Exception {
        Factory.register("李四",this);
    }
}

......

优化后代码

void OnlyStrategy(){
        String name = "小杰";
        if (name.equals("刘二")){
            new LiuEr().show();
        } else if (name.equals("张三")) {
            new ZhangSan().show();
        } else if (name.equals("李四")) {
            new LiSi().show();
        } else if (name.equals("王五")) {
            new WangWu().show();
        } else if (name.equals("赵六")) {
            new ZhaoLiu().show();
        } else if (name.equals("苏七")) {
            new SuQi().show();
        }
    }

2.引入工厂模式

分析代码

虽然我们引入了策略模式,但是仍然未解决if-else语句,并且每次使用策略都必须先new出来,后续拓展仍然需要添加if-else代码,这样看起来代码更加复杂了,性能更差了。别急,我们继续添加工厂模式,继续优化代码。

优化代码

我们定义一个工厂,让工厂帮我们去生产对应的对象。

public class Factory {
    //我们将策略类存入HashMap里面
    private static Map<String, Handler> map = new HashMap<>();

    //根据name获取对应的策略类
    public static Handler getInvokeStrategy(String name){
        return map.get(name);
    }
    //将策略类放入map里面
    public static void register(String name,Handler handler){
        if (StringUtils.isEmpty(name) || null == handler){
            return;
        }
        map.put(name,handler);
    }
}

这里给大家解释afterPropertiesSet()方法里面的逻辑

public class LiSi implements Handler{
    @Override
    public void show() {
        System.out.println("李四完成了任务");
    }
    
    @Override
    public void afterPropertiesSet() throws Exception {
        //策略类初始化后,自动将策略类注册到HashMap里面
        Factory.register("李四",this);
    }
}

优化后代码

//我们成功的干掉了if-else
void haveFactory(){
        String name = "张三";
        Handler handler = Factory.getInvokeStrategy(name);
        handler.show();
    }

3.引入模板方法模式

分析代码

到这里虽然我们成功的干掉了if-else语句,但是又引出了一个问题,

 String name = "小杰";
        if (name.equals("刘二")){
            System.out.println("刘二完成任务");
        } else if (name.equals("张三")) {
            System.out.println("张三完成任务");
        } else if (name.equals("李四")) {
            System.out.println("李四完成任务");
        } else if (name.equals("王五")) {
            return "王五完成了任务";
        } else if (name.equals("赵六")) {
            return "赵六完成任务";
        } else if (name.equals("苏七")) {
            return "苏七完成任务";
        }

我们可以看到,五五、赵六、苏七策略跟其他语句的策略并不一样。

解决思路:

  1.  在策略接口添加不同的策略(不使用)
  2. 使用模板方法模式,每个策略类实现自己对应的策略(推荐使用)

给大家解释下为什么不使用第一种,如果我们在策略接口添加不同的策略,我们的策略类就必须要实现所以的策略,但是策略类并不需要实现所有的策略,它只需要实现自己的那一个策略,所以这个思路不可行。

优化代码

我们将策略接口改为策略抽象类

public abstract class AbstractHandler implements InitializingBean {
    //策略1
    public void show(String name){ throw new UnsupportedOperationException();}
    //策略2
    public String eat(String name){ throw new UnsupportedOperationException();}
}

当然,我们的工厂和策略类也要修改,张三策略类和王五策略类实现不同的策略。


//策略工厂
public class Factory2 {
    //将Handler改为AbstractHandler
    private static Map<String, AbstractHandler> map = new HashMap<>();

    public static AbstractHandler getInvokeStrategy(String name){
        return map.get(name);
    }
    public static void register(String name,AbstractHandler handler){
        if (StringUtils.isEmpty(name) || null == handler){
            return;
        }
        map.put(name,handler);
    }
}
//张三策略类
@Component
public class WangWu extends AbstractHandler {

    @Override
    public String eat(String name) {
        return "王五吃东西";
    }

    @Override
    public void afterPropertiesSet() throws Exception {
        Factory2.register("王五",this);
    }
}
//王五策略
@Component
public class ZhangSan extends AbstractHandler {

    @Override
    public void show(String name) {
        System.out.println("张三完成了任务");
    }

    @Override
    public void afterPropertiesSet() throws Exception {
        Factory2.register("张三",this);
    }
}
......

优化后代码

 @Test
    void haveTemplate(){
        String name1 = "王五";
        AbstractHandler handler1 = Factory2.getInvokeStrategy(name1);
        System.out.println(handler1.eat(name1));
        String name2 = "张三";
        AbstractHandler handler2 = Factory2.getInvokeStrategy(name2);
        handler2.show(name2);
    }

随着通过我们一步步的添加设计模式,使我们的代码更加简洁,也符合了“开闭原则”,到这里,我们就优化完成了。


总结

        虽然设计模式帮助我们优化了代码,是代码更加的规范,但是,切不可为了使用设计模式而去使用设计模式,在某种业务场景使用if-else语句可能比设计模式更加适合,所以大家要结合业务场景,选出最优的解决方法。

今天的分享就到这里,喜欢的小伙伴可以一键三连哦,我们下期再见。✋✋✋

  • 15
    点赞
  • 19
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
代码中的条件语句if-else过于复杂时,可以考虑使用设计模式代替if-else语句,提高代码的可读性和可维护性。以下是一些常见的设计模式,可以用来代替if-else语句: 1. 工厂模式(Factory Pattern):通过工厂方法创建对象,而不是使用条件语句来直接创建对象。这样可以避免在代码中使用大量的if-else语句,同时也可以很方便地添加新的对象类型。 2. 状态模式(State Pattern):将复杂的状态判断逻辑封装到不同的状态类中,避免在代码中使用大量的if-else语句。可以很方便地添加新的状态类型,也可以方便地维护和扩展状态的行为。 3. 策略模式(Strategy Pattern):将不同的算法封装到不同的策略类中,通过选择不同的策略类来实现不同的行为。这样可以避免在代码中使用复杂的if-else语句,同时也可以很方便地添加新的算法类型。 4. 观察者模式(Observer Pattern):将一个对象的状态变化通知给多个观察者对象,避免在代码中使用大量的if-else语句。可以很方便地添加新的观察者对象,也可以方便地维护和扩展观察者的行为。 5. 责任链模式(Chain of Responsibility Pattern):将多个处理对象组成一个链,每个处理对象都可以处理请求,如果一个对象不能处理请求,则将请求传递给下一个处理对象。这样可以避免在代码中使用大量的if-else语句,同时也可以很方便地添加新的处理对象。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

小杰不秃头

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值