Spring中如何使用策略模式避免过多if-else代码

365 阅读1分钟

这是我参与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去处理新增的业务逻辑。