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去处理新增的业务逻辑。