if else 优化 策略模式+工厂模式
场景
在项目中有时候会遇到需要大量if else判断的时候,通常的if else 判断会造成代码整体不够优雅,可读性差, 可维护性差,且后续交给新手维护的时候可能会让人蒙圈,因而会想到通过一种方法来对这种情况进行优化,提高 自己技术的同时也让自己参与的项目更便于维护,何乐而不为呢。
下面先看一下原始代码的写法,然后再提出优化后的代码,大家可以对比一下其中的不同
controller
controller通过依赖注入调用dialogueLogV3Service.saveDialogueLog(dialogueLog)方法;
service
service层通过依赖注入执行具体的业务逻辑方法
原始代码
@Override @Transactional(rollbackFor = Exception.class) public int saveDialogueLog(DialogueLog dialogueLog) { //保存提交信息 int i = insertDialogueLog(dialogueLog); //保存对话信息 UserChatRecord userChatRecord = updateUserChatRecord(dialogueLog); if (Constants.QUESTION_TYPE.ONE.getValue().equals(dialogueLog.getType())){ //业务逻辑代码...... }else if(Constants.QUESTION_TYPE.TWO.getValue().equals(dialogueLog.getType())) { //业务逻辑代码...... }else if (Constants.QUESTION_TYPE.THREE.getValue().equals(dialogueLog.getType())) { //业务逻辑代码...... }else if (Constants.QUESTION_TYPE.FOUR.getValue().equals(dialogueLog.getType())) { //业务逻辑代码...... }else if (Constants.QUESTION_TYPE.FIVE.getValue().equals(dialogueLog.getType())) { //业务逻辑代码...... }else if (Constants.QUESTION_TYPE.SIX.getValue().equals(dialogueLog.getType())) { //业务逻辑代码...... }else if (Constants.QUESTION_TYPE.SEVEN.getValue().equals(dialogueLog.getType())) { //业务逻辑代码...... }else if (Constants.QUESTION_TYPE.EIGHT.getValue().equals(dialogueLog.getType())) { //业务逻辑代码...... }else if (Constants.QUESTION_TYPE.NINE.getValue().equals(dialogueLog.getType())) { //业务逻辑代码...... }else if (Constants.QUESTION_TYPE.TEN.getValue().equals(dialogueLog.getType())) { //业务逻辑代码...... }else if (Constants.QUESTION_TYPE.ELEVEN.getValue().equals(dialogueLog.getType())) { //业务逻辑代码...... }else if (Constants.QUESTION_TYPE.TWELVE.getValue().equals(dialogueLog.getType())) { //业务逻辑代码...... }else if (Constants.QUESTION_TYPE.THIRTEEN.getValue().equals(dialogueLog.getType())) { //业务逻辑代码...... }else if (Constants.QUESTION_TYPE.FOURTEEN.getValue().equals(dialogueLog.getType()) || Constants.QUESTION_TYPE.TWENTY_SIX.getValue().equals(dialogueLog.getType()) || Constants.QUESTION_TYPE.THIRTY_FOUR.getValue().equals(dialogueLog.getType()) || Constants.QUESTION_TYPE.THIRTY_SEVEN.getValue().equals(dialogueLog.getType()) || Constants.QUESTION_TYPE.SIXTEEN.getValue().equals(dialogueLog.getType()) || Constants.QUESTION_TYPE.FIFTEEN.getValue().equals(dialogueLog.getType()) || Constants.QUESTION_TYPE.TWENTY_SEVEN.getValue().equals(dialogueLog.getType()) || Constants.QUESTION_TYPE.THIRTY_FIVE.getValue().equals(dialogueLog.getType()) || Constants.QUESTION_TYPE.THIRTY_EIGHT.getValue().equals(dialogueLog.getType()) || Constants.QUESTION_TYPE.TWENTY_NINE.getValue().equals(dialogueLog.getType())) { //业务逻辑代码...... }else if (Constants.QUESTION_TYPE.SEVENTEEN.getValue().equals(dialogueLog.getType()) || Constants.QUESTION_TYPE.EIGHTTEEN.getValue().equals(dialogueLog.getType())) { //业务逻辑代码...... }else if (Constants.QUESTION_TYPE.NINETEEN.getValue().equals(dialogueLog.getType())) { //业务逻辑代码...... }else if (Constants.QUESTION_TYPE.TWENTY.getValue().equals(dialogueLog.getType()) || Constants.QUESTION_TYPE.TWENTY_FOUR.getValue().equals(dialogueLog.getType()) || Constants.QUESTION_TYPE.TWENTY_ONE.getValue().equals(dialogueLog.getType()) || Constants.QUESTION_TYPE.TWENTY_FIVE.getValue().equals(dialogueLog.getType()) || Constants.QUESTION_TYPE.THIRTY_SIX.getValue().equals(dialogueLog.getType()) || Constants.QUESTION_TYPE.THIRTY_NINE.getValue().equals(dialogueLog.getType())) { //业务逻辑代码...... }else if (Constants.QUESTION_TYPE.TWENTY_TWO.getValue().equals(dialogueLog.getType()) || Constants.QUESTION_TYPE.TWENTY_THREE.getValue().equals(dialogueLog.getType())) { //业务逻辑代码...... }else if (Constants.QUESTION_TYPE.THIRTY.getValue().equals(dialogueLog.getType()) || Constants.QUESTION_TYPE.THIRTY_ONE.getValue().equals(dialogueLog.getType())) { //业务逻辑代码...... }else if (Constants.QUESTION_TYPE.THIRTY_TWO.getValue().equals(dialogueLog.getType()) || Constants.QUESTION_TYPE.THIRTY_THREE.getValue().equals(dialogueLog.getType())) { //业务逻辑代码...... }else if (Constants.QUESTION_TYPE.FORTY.getValue().equals(dialogueLog.getType()) || Constants.QUESTION_TYPE.FORTY_ONE.getValue().equals(dialogueLog.getType())) { //业务逻辑代码...... }else if (Constants.QUESTION_TYPE.FORTY_TWO.getValue().equals(dialogueLog.getType())) { //业务逻辑代码...... }else if (Constants.QUESTION_TYPE.FORTY_FOUR.getValue().equals(dialogueLog.getType()) || Constants.QUESTION_TYPE.FORTY_FIVE.getValue().equals(dialogueLog.getType()) || Constants.QUESTION_TYPE.FORTY_SIX.getValue().equals(dialogueLog.getType())) { //业务逻辑代码...... }else if (Constants.QUESTION_TYPE.FIFTY.getValue().equals(dialogueLog.getType())) { //业务逻辑代码...... }else if (Constants.QUESTION_TYPE.FIFTY_ONE.getValue().equals(dialogueLog.getType())) { //业务逻辑代码...... }else if (Constants.QUESTION_TYPE.FIFTY_TWO.getValue().equals(dialogueLog.getType())) { //业务逻辑代码...... }else if (Constants.QUESTION_TYPE.FORTY_NINE.getValue().equals(dialogueLog.getType())){ //业务逻辑代码...... }else if (Constants.QUESTION_TYPE.FORTY_EIGHT.getValue().equals(dialogueLog.getType())){ //业务逻辑代码...... }else if (Constants.QUESTION_TYPE.FIFTY_THREE.getValue().equals(dialogueLog.getType())){ //业务逻辑代码...... }else if (Constants.QUESTION_TYPE.FIFTY_FOUR.getValue().equals(dialogueLog.getType())){ //业务逻辑代码...... }else if (Constants.QUESTION_TYPE.FIFTY_FIVE.getValue().equals(dialogueLog.getType())){ //业务逻辑代码...... }else if (Constants.QUESTION_TYPE.FIFTY_SIX.getValue().equals(dialogueLog.getType())){ //业务逻辑代码...... }else if (Constants.QUESTION_TYPE.FIFTY_SEVEN.getValue().equals(dialogueLog.getType()) || Constants.QUESTION_TYPE.SIXTY.getValue().equals(dialogueLog.getType())){ //业务逻辑代码...... }else if (Constants.QUESTION_TYPE.FIFTY_EIGHT.getValue().equals(dialogueLog.getType())){ //业务逻辑代码...... }else if (Constants.QUESTION_TYPE.FIFTY_NINE.getValue().equals(dialogueLog.getType())){ //业务逻辑代码...... }else if (Constants.QUESTION_TYPE.SIXTY_ONE.getValue().equals(dialogueLog.getType())) { //业务逻辑代码...... }else if (Constants.QUESTION_TYPE.SIXTY_THREE.getValue().equals(dialogueLog.getType()) || Constants.QUESTION_TYPE.SIXTY_FOUR.getValue().equals(dialogueLog.getType())) { //业务逻辑代码...... }else if (Constants.QUESTION_TYPE.SIXTY_FIVE.getValue().equals(dialogueLog.getType())) { //业务逻辑代码...... } return i; }
可以看到有很多if else 判断,并且后续每增加一种类型,这里就需要加一个else if 判断,后面开发这阅读起来单从方法行数上就有点蒙圈了,具体业务逻辑更是难懂了,很不利于后期维护。
策略模式+工厂模式
鉴于以上的情况,于是考虑通过设计模式的方向解决代码量大,阅读困难,维护成本高的问题
解决方案
基于当前业务区分主要与QUESTION_TYPE 相关,不同的QUESTION_TYPE对应不同的业务处理逻辑。那么套用策略模式的描述就是说一个系统里面有许多类,它们之间的区别仅在于它们的行为,那么使用策略模式可以动态地让一个对象在许多行为中选择一种行为;或者说是一个类的行为或其算法可以在运行时更改。
创建一个接口
声明业务处理方法operation
public interface QuestionTypeService { /** * 业务操作方法 */ public void operation(Object object); }
创建QUESTION_TYPE 对应的实现类
实现接口声明方法中的具体业务逻辑
QUESTION_TYPE实现类一
@Service public class QuestionOneServiceImpl implements QuestionTypeService { @Override public void operation(Object object) { //具体的业务处理逻辑 } } @Service public class QuestionTwoServiceImpl implements QuestionTypeService { @Override public void operation(Object object) { //具体的业务处理逻辑 } } ............
QUESTION_TYPE实现类二
@Service public class QuestionOneServiceImpl implements QuestionTypeService { @Autowired private UserPhysicalLogMapper userPhysicalLogMapper; @PostConstruct public void init() { BusinessFactory.register(Constants.QUESTION_TYPE.ONE.getValue(),this); } @Override public void operation(Object object) { //具体的业务处理逻辑 } } @Service public class QuestionTwoServiceImpl implements QuestionTypeService { @Autowired private ITimingMessageService timingMessageService; @PostConstruct public void init() { BusinessFactory.register(Constants.QUESTION_TYPE.TWO.getValue(),this); } @Override public void operation(Object object) { //具体业务处理逻辑 } } ............
此方法@Service表明该类将自动注册到Spring容器
创建BusinessFactory工厂类
工厂模式通俗理解就是说我不需要知道具体产品是怎么生产出来的,我只需要知道我需要什么产品然后从工厂提货就可以了,这里我告诉工厂我需要QuestionOneServiceImpl,然后工厂替我创建好对应的bean并交给spring管理
工厂类一
@Component public class BusinessFactory { public QuestionTypeService getQuestionType(Integer type){ if(type == null){ return null; } if(Constants.QUESTION_TYPE.ONE.getValue().equals(type)){ return SpringUtils.getBean(QuestionOneServiceImpl.class); } return null; } }
工厂类二
@Component public class BusinessFactory { private static Map<Integer,QuestionTypeService> map = new HashMap(128); public static void register(Integer type,QuestionTypeService questionTypeService) { map.put(type,questionTypeService); } /** * 获取业务实现类 * @param type * @return */ public QuestionTypeService getQuestionType(Integer type){ if(type == null){ return null; } return map.get(type); } }
此方法@Component表明该类将自动注册到Spring容器,此处用SpringUtils.getBean(QuestionOneServiceImpl.class); 或者SpringUtils.getBean(“questionOneServiceImpl”);而来获取子项实例是将获取的子项实例交给spring容器,这样避免直接new对象的时候后续需要依赖注入对象时为null的问题。
SpringUtils.java
package com.ruoyi.common.utils.spring; import org.springframework.aop.framework.AopContext; import org.springframework.beans.BeansException; import org.springframework.beans.factory.NoSuchBeanDefinitionException; import org.springframework.beans.factory.config.BeanFactoryPostProcessor; import org.springframework.beans.factory.config.ConfigurableListableBeanFactory; import org.springframework.stereotype.Component; /** * spring工具类 方便在非spring管理环境中获取bean * */ @Component public final class SpringUtils implements BeanFactoryPostProcessor { /** Spring应用上下文环境 */ private static ConfigurableListableBeanFactory beanFactory; @Override public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException { SpringUtils.beanFactory = beanFactory; } /** * 获取对象 * * @param name * @return Object 一个以所给名字注册的bean的实例 * @throws org.springframework.beans.BeansException * */ @SuppressWarnings("unchecked") public static <T> T getBean(String name) throws BeansException { return (T) beanFactory.getBean(name); } /** * 获取类型为requiredType的对象 * * @param clz * @return * @throws org.springframework.beans.BeansException * */ public static <T> T getBean(Class<T> clz) throws BeansException { T result = (T) beanFactory.getBean(clz); return result; } /** * 如果BeanFactory包含一个与所给名称匹配的bean定义,则返回true * * @param name * @return boolean */ public static boolean containsBean(String name) { return beanFactory.containsBean(name); } /** * 判断以给定名字注册的bean定义是一个singleton还是一个prototype。 如果与给定名字相应的bean定义没有被找到,将会抛出一个异常(NoSuchBeanDefinitionException) * * @param name * @return boolean * @throws org.springframework.beans.factory.NoSuchBeanDefinitionException * */ public static boolean isSingleton(String name) throws NoSuchBeanDefinitionException { return beanFactory.isSingleton(name); } /** * @param name * @return Class 注册对象的类型 * @throws org.springframework.beans.factory.NoSuchBeanDefinitionException * */ public static Class<?> getType(String name) throws NoSuchBeanDefinitionException { return beanFactory.getType(name); } /** * 如果给定的bean名字在bean定义中有别名,则返回这些别名 * * @param name * @return * @throws org.springframework.beans.factory.NoSuchBeanDefinitionException * */ public static String[] getAliases(String name) throws NoSuchBeanDefinitionException { return beanFactory.getAliases(name); } /** * 获取aop代理对象 * * @param invoker * @return */ @SuppressWarnings("unchecked") public static <T> T getAopProxy(T invoker) { return (T) AopContext.currentProxy(); } }
业务调用
优化后代码
@Override @Transactional(rollbackFor = Exception.class) public int saveDialogueLog(DialogueLog dialogueLog) { //保存提交信息 int i = insertDialogueLog(dialogueLog); //保存对话信息 UserChatRecord userChatRecord = updateUserChatRecord(dialogueLog); QuestionTypeService questionTypeService = businessFactory.getQuestionType(dialogueLog.getType()); questionTypeService.operation(dialogueLog); return i; }
这样就将每一种判断分开来而不用造成一个巨大臃肿的方法造成维护阅读两难的困境。