欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

重构大量if-else语句: 工厂模式+策略设计模式+模板模式

程序员文章站 2022-06-19 15:12:49
重构大量if-else叠加: 工厂模式+策略设计模式+模板模式现有三个简单的if-else判断逻辑业务代码,如下图所示这种嵌套几个其实还好,但是通常开发十几个if-else确实是家常便饭if-else的数量一多,代码非常臃肿,耦合性非常高如果需要增加或者删除一个if-else...

重构大量if-else叠加: 工厂模式+策略设计模式+模板模式

现有三个简单的if-else判断逻辑业务代码,如下图所示

这种嵌套几个其实还好,但是通常开发十几个if-else确实是家常便饭

if-else的数量一多,代码非常臃肿,耦合性非常高

如果需要增加或者删除一个if-else,就需要对代码进行很繁琐的修改,但是其实耐心点改起来还好,不过可能会掉头发哦

并且这种if-else的编写破坏了设计模式六大原则中的里氏开闭原则(对拓展开放,修改关闭),不利于后续的变动和修改

为了使代码符合优雅的设计模式和编码形式,现在提供一种新的修改思路供大家参考

以下是改造前的代码:


// 三个if - else 的编码修改
@SpringBootTest
class ConcurrencyApplicationTests {

    @Test
    void contextLoads() throws InterruptedException {
        String name = "周杰伦";
        if (name.equals("周杰伦")){
            for (int i = 0; i < 5; i++) {
                System.out.println(name + "我爱你");
            }
            System.out.println("周杰伦出新专辑了吗");
        }
        else if (name.equals("JJ")){
            for (int i = 0; i < 5; i++) {
                System.out.println(name + "我爱你");
            }
            System.out.println("小十四啥时候出哦");
        }
        else if (name.equals("Eason")){
            for (int i = 0; i < 5; i++) {
                System.out.println(name + "我爱你");
            }
            System.out.println("陈老板减肥啊");
        }
    }

}


改造后:
@SpringBootTest
class ConcurrencyApplicationTests {

    @Test
    void contextLoads() {
        String name = "周杰伦";
        Handler invokeStrategy = Factory.getInvokeStrategy(name);
        invokeStrategy.method(name);
    }
}
使用设计模式的改造方法

我们先把if内部的业务逻辑提取出来

利用策略设计模式来编写一个接口

/**
 * 策略设计模式
 */ public interface Handler extends InitializingBean { public void method(String name); } 

将你的业务逻辑从if中提取出来,写在实现类中

package com.zhou.concurrency.handler;

import java.util.concurrent.TimeUnit;

public class Method1Handler implements Handler {
    @Override
    public void method(String name)  {
        for (int i = 0; i < 5; i++) {
            System.out.println(name + "我爱你");
        }
        System.out.println("周杰伦啥时候发新专辑哦");
    }

    // 这里先不用管,后面会说到
    @Override
    public void afterPropertiesSet() throws Exception {

    }
}
剩下的几个类就省略了,其实就是复制粘贴的重复工作

将其修改成如下形式,但是这个也只是将其单独提出来,和写一个单独的函数没啥区别

@Test
    void contextLoads() {
        String name = "周杰伦";
        if (name.equals("周杰伦")){
            new Method1Handler().method(name);
        }
        else if (name.equals("JJ")){
            new Method2Handler().method(name);
        }
        else if (name.equals("Eason")){
            new Method3Handler().method(name);
        }
    }
为了进一步解决if判断,我们使用工厂模式解决

工厂模式可以注册产品,获得产品,以及存储产品

public class Factory {
    // map存储参数以及其对应的Handler方法
    private static Map<String, Handler> strategyMap = new HashMap<>();

    // 从map中取出Handler方法,取出工厂内的产品
    public static Handler getInvokeStrategy(String str) {
        return strategyMap.get(str);
    }

    // 将键值对注册,添加工厂产品
    public static void register(String str, Handler handler) {
        // 如果输入进来的键值是空,不符合要求就直接返回
        if (StringUtils.isEmpty(str) || handler == null) {
            throw new IllegalArgumentException("你输入的键值对有空值,不符合要求");
        }
        strategyMap.put(str,handler);
    }
}
之后,修改一下之前的Handler实现类,并加入@Component注解,其他的几个业务逻辑同理
@Component
public class Method1Handler implements Handler {
    // 业务逻辑
    @Override
    public void method(String name)  {
        for (int i = 0; i < 5; i++) {
            System.out.println(name + "我爱你");
        }
        System.out.println("周杰伦啥时候发新专辑哦");
    }

    // 类初始化自动注册
    @Override
    public void afterPropertiesSet() throws Exception {
        // 这个类初始化的时候,就会自动注册
        Factory.register("周杰伦",this);
    }
}
回到主函数, 改写一下即可:
@SpringBootTest
class ConcurrencyApplicationTests {

    @Test
    void contextLoads() {
        String name = "周杰伦";
        Handler invokeStrategy = Factory.getInvokeStrategy(name);
        invokeStrategy.method(name);
    }
}
后续如果还需要增加业务逻辑,就新增加一个Handler的实现类就好了

加模板设计方法

如果业务逻辑是两种业务逻辑,比如有的是输出一句话,有的是return一句话

那么Handler单一的method接口可能就不适用了,因为你在接口多写一个方法,其他不需要的地方你实现一个空方法,肯定要被老大骂的

@SpringBootTest
class ConcurrencyApplicationTests {

    @Test
    String design(){
        String name = "周杰伦";
        if (name.equals("周杰伦")){
            for (int i = 0; i < 5; i++) {
                System.out.println(name + "我爱你");
            }
            System.out.println("周杰伦出新专辑了吗");
        }
        else if (name.equals("JJ")){
            for (int i = 0; i < 5; i++) {
                System.out.println(name + "我爱你");
            }
            System.out.println("小十四啥时候出哦");
        }
        else if (name.equals("Eason")){
            for (int i = 0; i < 5; i++) {
                System.out.println(name + "我爱你");
            } 
            System.out.println("陈老板减肥啊");
        }
				// 新增加的逻辑代码 返回值
        else if (name.equals("jojo")){
            return "欧拉欧拉欧拉欧拉";
        }
        else if (name.equals("老大")){
            return "进展如何";
        }

        return null;
    }

}
改进一下我们的Handler类,引入模板方法模式
// 模板方法模式
public abstract class AbstractHandler implements InitializingBean {

    public void method(String name){
        throw new UnsupportedOperationException();
    }

    public String method2(String name){
        throw new UnsupportedOperationException();
    }
}
需要用到method就改写method,需要用到method2就改写method2
@Component
public class Method4Handler extends AbstractHandler {
    // 业务逻辑

    public String method2(String name)  {
        return "进展如何";
    }

    // 这里不用管
    @Override
    public void afterPropertiesSet() throws Exception {
        // 这个类初始化的时候,就会自动注册
        Factory.register("老大",this);
    }
}
最终代码:
@Test
void contextLoads() {
    String name = "老大";
    AbstractHandler invokeStrategy = Factory.getInvokeStrategy(name);
    // invokeStrategy.method(name);
    String s = invokeStrategy.method2(name);
    System.out.println(s);
}
本文地址:https://blog.csdn.net/qq_42669399/article/details/107889601