(三)让代码更优雅系列(枚举策略去除if-else及其注入bean)

472 阅读2分钟

前言

个人经验,if-else如果嵌套超过3层的话,可读性和可维护性就会急剧下降,强迫症代码洁癖的coder哪能受的了?所以本文介绍一种策略模式的延申:枚举策略

场景举例

众所周知,电商平台活动的促销五花八门,每种活动的计算逻辑都会比较复杂,这里的一个接口就是根据活动code来实现对应的计算逻辑:

public BigDecimal calculate(String activityCode) {
    if ("manjian".equals(activityCode)) {
        return BigDecimal.ZERO;
    } else if ("miaosha".equals(activityCode)) {
        return BigDecimal.ZERO;
    } else if ("lijian".equals(activityCode)) {
        return BigDecimal.ZERO;
    } else if ("youhuiquan".equals(activityCode)) {
        return BigDecimal.ZERO;
    }
    return BigDecimal.ZERO;
}

那上面的if-else我们怎么消灭呢?

优雅转身

public enum DiscountStrategyEnum {

    MANJIAN {
        @Override
        public BigDecimal cal() {
            return null;
        }
    },

    MIAOSHA {
        @Override
        public BigDecimal cal() {
            return null;
        }
    },

    LIJIAN {
        @Override
        public BigDecimal cal() {
            return null;
        }
    },

    YOUHUIQUAN {
        @Override
        public BigDecimal cal() {
            return null;
        }
    }

    ;
    public abstract BigDecimal cal();
}

常见问题

很多人常常会问枚举里面不能注入bean导致很多逻辑没法处理,其实最简单的方法就是定义一个获取bean的工具类,用其静态方法获取就好了,比如:

@Component
public class SpringUtils implements ApplicationContextAware {

    private static ApplicationContext applicationContext;

    @Override
    public void setApplicationContext(ApplicationContext applicationContext)
        throws BeansException {
        if (SpringUtils.applicationContext == null) {
            SpringUtils.applicationContext = applicationContext;
        }
    }

    public static ApplicationContext getApplicationContext() {
        return applicationContext;
    }

    //根据name
    public static Object getBean(String name) {
        return getApplicationContext().getBean(name);
    }

    //根据类型
    public static <T> T getBean(Class<T> clazz) {
        return getApplicationContext().getBean(clazz);
    }

    public static <T> T getBean(String name, Class<T> clazz) {
        return getApplicationContext().getBean(name, clazz);
    }
}

枚举里:

public enum DiscountStrategyEnum {

    MANJIAN(1) {
        @Override
        public BigDecimal cal() {
            return SpringUtils.getBean(ActivityCalService.class).handle();
        }
    },

    MIAOSHA(2) {
        @Override
        public BigDecimal cal() {
            return SpringUtils.getBean(ActivityCalService.class).handle();
        }
    },

    LIJIAN(3) {
        @Override
        public BigDecimal cal() {
            return SpringUtils.getBean(ActivityCalService.class).handle();
        }
    },

    YOUHUIQUAN(4) {
        @Override
        public BigDecimal cal() {
            return SpringUtils.getBean(ActivityCalService.class).handle();
        }
    };


    private int code;

    DiscountStrategyEnum(int code) {
        this.code = code;
    }

    public static BigDecimal calByCode(int code) {
        for (DiscountStrategyEnum value : DiscountStrategyEnum.values()) {
            if (value.code == code) {
                return value.cal();
            }
        }
        return null;
    }

    ;
    public abstract BigDecimal cal();
}

使用:

public BigDecimal calculateByEnum(Integer activityCode) {
    return DiscountStrategyEnum.calByCode(activityCode);
}

总结

枚举策略其实非常实用,通过使用枚举实现策略模式,我们能够以更加紧凑和清晰的方式管理不同的策略。这种方式不仅减少了代码的复杂性,还提高了代码的可维护性和扩展性。