使用(Map+Function函数式接口)或(注解+策略模式)优化switch case


前言

        在开发中,发现之前的小伙伴在使用switch case时并不优雅,导致一个switch case的代码块超过了上百行代码,给后来者的维护开发工作带来了极大的困扰。

        当我们需要用到switch case作为分支判断时,如果层数是4/5层时其实还好,将代码块抽成方法也比较精简,但是当swicth case的层数越变越多,每增加一个分支都需要在原来的代码块中做修改的话,这并不符合开闭原则,我们就需要一些手段来将其优化了,这里给大家列举两种方式来进行优化。

switch (type){
            case 1 -> method1();
            case 2 -> method2();
            case 3 -> method3();
            case 4 -> method4();
            case 5 -> method5();
            default -> method2();
        }   
}

两种优化方案

1.基于Map+Function函数式接口

       使用Map集合存储类型与方法的对应关系,使用Function函数式接口来简化方法的调用,其中type可以使用枚举类定义,直接上代码:

public class SwitchFactory {
    Map<Integer, Function<Object, Object>> map = new HashMap<>();

    private static SwitchFactory instance;

    // 使用单例模式实例化当前工厂类实例
    public static SwitchFactory getInstance() {
        if (instance == null) {
            synchronized (SwitchFactory.class) {
                if (instance == null) {
                    instance = new SwitchFactory();
                }
            }
        }
        return instance;
    }

    SwitchFactory(){
        // 初始化定义
        map.put(1, this::function1);
        map.put(2, this::function2);
        map.put(3, this::function3);
        map.put(4, this::function4);
    }
    
    // 传入type来获取需要执行的方法,type可以使用枚举类的方式来代替
    public Function<Object, Object> getFunction(Integer type){
        return map.get(type);
    }

    private Object function1(Object data) {
        return "分支1";
    }

    private Object function2(Object data) {
        return "分支2";
    }

    private Object function3(Object data) {
        return "分支3";
    }

    private Object function4(Object data) {
        return "分支4";
    }


}

此时,可以将原本的switch case代码块换成如下代码:

public static void main(String[] args){
        SwitchFactory switchFactory = SwitchFactory.getInstance();
        // type可用枚举类代替
        Integer type=1;
        Map data=new HashMap();
        // 方法调用
        String res =(String) switchFactory.getFunction(type).apply(data);

        System.out.println(res);
}

2.基于注解+Enum+策略模式

        第一种方案只需要创建一个类,然后增加方法就可以了。当业务逻辑十分相似且较为复杂时,我们可以通过策略模式将 “业务逻辑” 进行抽象, 只用一个注解的形式来实现动态增减分支,而开发人员只需关注具体业务逻辑实现即可。

1、首先定义分支条件type的常量值的枚举类CaseEnum

public enum CaseEnum {
    ACCEPT,
    READ,
    WRITE;
}

2. 定义注解CaseAnnotation,这个注解将用于“方法操作逻辑实现类”之上,标记该类是其中一个分支

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface CaseAnnotation {
    CaseEnum value();
}

3. 通过策略模式将 “业务逻辑” 进行抽象,定义一个接口,并实现一个分支,其它分支同理

/**
 * @Description: 分支统一接口
 */
public interface CaseInterface {
    String execute(Map<String,Object> data) throws Exception;
}
/**
 * @Description: accept分支逻辑处理
 */
@Component
@CaseAnnotation(value = CaseEnum.ACCEPT)
public class AcceptImpl implements CaseInterface{
    @Override
    public String execute(Map<String, Object> data) throws Exception {
        return "接收逻辑处理";
    }
}

4. 在项目启动的过程中,扫描CaseAnnotation注解获取所有分支实现类,通过 Map<String,CaseInterface> 实现枚举值和分支实现类的映射

/**
 * @Description: 获取spring应用上下文工具类
 */
@Component
public class SpringContextUtil implements ApplicationContextAware {
    private ApplicationContext context;

    @Override
    public void setApplicationContext(ApplicationContext context) throws BeansException {
        this.context=context;
    }

    //获取spring应用上下文(容器)-进而准备获取相应的bean
    public ApplicationContext getContext(){
        return context;
    }
}
/**
 * @Description: 实现枚举值和分支实现类的映射
 */
@Component
public class InitCaseBeanMapComponent {
    public static Map<CaseEnum,CaseInterface> processMap=new ConcurrentHashMap<>();

    @Autowired
    private SpringContextUtil springContextUtil;

    @PostConstruct
    public void init() {
        //获取那些带上了注解的 处理实现类
        Map<String,Object> map=springContextUtil.getContext().getBeansWithAnnotation(CaseAnnotation.class);

        //添加 case常量值~方法操作逻辑实现类 映射
        for (Object process:map.values()){
            CaseAnnotation annotation=process.getClass().getAnnotation(CaseAnnotation.class);
            processMap.put(annotation.value(),(CaseInterface) process);
        }
    }

    public Map<CaseEnum,CaseInterface> getProcessMap(){
        return processMap;
    }
}

此时,可以将原本的switch case代码块换成如下代码:

Map<String,Object> data = new HashMap<>();

CaseInterface case=InitCaseBeanMapComponent.processMap.get(CaseEnum.ACCEPT);
String res = case.execute(data);


总结

1. 基于Map+Function函数式接口方式,只需要新建一个类,在类中增加分支方法即可,但当业务逻辑较为复杂,类的体积将会变的较大。

2. 基于注解+Enum+策略模式的方式,适合业务逻辑十分相似且较为复杂的场景,可以发现改造过后代码比原本的更多了,但当分支越来越多时,这无疑是值得的

  • 2
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值