小言_互联网的博客

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

269人阅读  评论(0)

重构大量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
查看评论
* 以上用户言论只代表其个人观点,不代表本网站的观点或立场