前言
个人经验,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);
}
总结
枚举策略其实非常实用,通过使用枚举实现策略模式,我们能够以更加紧凑和清晰的方式管理不同的策略。这种方式不仅减少了代码的复杂性,还提高了代码的可维护性和扩展性。