这是我参与8月更文挑战的第1天,活动详情查看:8月更文挑战
1、场景描述
我们经常在项目中,会看到如下所示if-else过多的代码。如果条件过多的话逻辑就比较混乱,也容易出错。如果新增一种业务,又要来增加一个if else,即难以维护,阅读性也很差。
if(a){
}else if(b){
}else if(c){
}else{
}
什么是策略模式?
策略模式是一种解耦的方法,它对算法进行封装,使得算法的调用和算法本身分离。使用策略模式,客户端代码不需要调整,算法之间可以互相替换,因为不同的算法实现的是同一个接口。
下面我们就以一个实际例子讲解如何使用策略模式避免使用过多的if-else语句。
2、定义策略接口
public interface BusinessExecutor {
void handleMessage(String record);
}
3、实现策略
根据不同策略,实现接口,重写处理逻辑。
@Slf4j
@Component("simpleBusinessExecutor")
public class SimpleBusinessExecutor implements BusinessExecutor {
@Override
public void handleMessage(String record) {
log.info("simple {}", record);
}
}
@Slf4j
@Component("intentBusinessExecutor")
public class IntentBusinessExecutor implements BusinessExecutor {
@Override
public void handleMessage(String record) {
log.info("intent {}",record);
}
}
4、策略管理
定义策略上下文,由于Spring IOC已经通过反射机制将类实例化到容器中了,因此我们只需要根据业务类型获取对象实例,这里我们使用ApplicationContext来获取策略对象实例Bean。
@Slf4j
@Component
public class BusinessExecutorManager {
@Autowired
private ApplicationContext applicationContext;
public BusinessExecutor getExecutor(Byte type) {
BussinessTypeEnum[] values = BussinessTypeEnum.values();
if (values.length <= 0) {
return null;
}
for (BussinessTypeEnum value : values) {
try {
if (Objects.equals(type, value.getCode())) {
return (BusinessExecutor) applicationContext.getBean(value.getBeanName());
}
} catch (Exception e) {
log.error("获取BusinessExecutor异常", e);
return null;
}
}
return null;
}
}
在这一步骤中,我们需要一种方式可以根据业务类型type来反射获取对象的实例,这里使用枚举来维护二者的对应关系。
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.NoArgsConstructor;
@Getter
@NoArgsConstructor
@AllArgsConstructor
public enum BussinessTypeEnum {
INTENT_BUSINESS(Byte.parseByte("1"), "intentBusinessExecutor", "简单业务"),
SIMPLE_BUSINESS(Byte.parseByte("2"), "simpleBusinessExecutor", "意图业务");
private Byte code;
private String beanName;
private String desc;
}
但是这里还有一个不够优雅的地方,就是业务类型type和处理类的映射关系还是需要手动维护,不够智能。
5、运行(使用策略)
@Slf4j
@Component
public class ModelMessage {
@Autowired
private BusinessExecutorManager businessExecutorManager;
protected void execute() {
Byte bussinessType = Byte.parseByte("1");
String message = "test";
BusinessExecutor businessExecutor = businessExecutorManager.getExecutor(bussinessType);
if(businessExecutor!=null){
businessExecutor.handleMessage(message);
}
}
}
结果如下:
simple test
现在,如果新增业务逻辑,只需要再增加一个类来处理策略就可以了。每个处理逻辑都互相独立互不干扰。无需增加else-if去处理新增的业务逻辑。