基本邏輯如下:
String event = crsRequest.getEvent(); CRSResponse crsResponse = null; switch (event) { case CRSRequestEvent.APP_START: crsResponse = processAppStartCommand(crsRequest); break; case CRSRequestEvent.INIT_COMPLETE: crsResponse = processInitCompleteCommand(crsRequest); break; case CRSRequestEvent.COLLECT_COMPLETE: crsResponse = processCollectCompleteCommand(crsRequest); break; case CRSRequestEvent.COLLECT_NO_INPUT: crsResponse = processCollectNoInputCommand(crsRequest); break; case CRSRequestEvent.PLAY_COMPLETE: crsResponse = processPlayCompleteCommand(crsRequest); break; default: }
寫完會發現,隨著事件的增加,這段程式碼會很長,每個事件的處理函數也都集中在一個類別當中,不好維護。因此,透過搜尋學習發現,可以使用Springboot的註解 策略模式 簡單工廠的方式來消除switch-case。
重構
定義結構體
public enum CRSEvent { APP_START("APP_START"), INIT_COMPLETE("INIT_COMPLETE"), PLAY_COMPLETE("PLAY_COMPLETE"), COLLECT_COMPLETE("COLLECT_COMPLETE"), COLLECT_NO_INPUT("COLLECT_NO_INPUT"), APP_END("APP_END"), RESP_ERROR_CMD("RESP_ERROR_CMD"); private String event; CRSEvent(String event){ this.event = event; } public String getEvent() { return event; } public void setEvent(String event) { this.event = event; } }
定義一個註解
@Target(ElementType.TYPE) @Retention(RetentionPolicy.RUNTIME) public @interface CRSEventAnnotation { CRSEvent value(); }
定義事件處理介面
public interface EventProcess { CRSResponse execute(CRSRequest resquest); }
所有的時間處理類別都要實作這個介面。其中,execute是事件的處理方法
寫具體的時間處理類別
接下來,逐一的寫事件處理類,舉下面一個例子:
@Component("appStartProcess") @CRSEventAnnotation(value = CRSEvent.APP_START) public class AppStartProcess implements EventProcess{ @Override public CRSResponse execute(CRSRequest resquest) { CRSResponse response = new CRSResponse(); response.setCommand(CRSResponseCmd.IVR_SESSION_INIT); CRSResponse.Message message = new CRSResponse.Message(); message.setTts_vid("65580"); message.setTts_speed("120"); response.setMessage(message); return response; } }
定義SpringContext工具類別
@Component public class SpringContextUtil implements ApplicationContextAware{ private ApplicationContext context; public ApplicationContext getContext(){ return context; } @Override public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { this.context = applicationContext; } }
定義事件處理類別工廠,用來生產各種事件處理物件
@Component public class EventProcessFactory { @Autowired SpringContextUtil contextUtil; private static Map<CRSEvent, EventProcess> eventProcessMap = new ConcurrentHashMap<>(); public EventProcessFactory() { Map<String, Object> beanMap = contextUtil.getContext().getBeansWithAnnotation(CRSEventAnnotation.class); for (Object evetProcess : beanMap.values()) { CRSEventAnnotation annotation = evetProcess.getClass().getAnnotation(CRSEventAnnotation.class); eventProcessMap.put(annotation.value(), (EventProcess) evetProcess); } } public static EventProcess createEventProcess(CRSEvent event){ return eventProcessMap.get(event); } }
呼叫程式碼修改
CRSEvent crsEvent = CRSEvent.valueOf(crsRequest.getEvent()); EventProcess eventProcess = EventProcessFactory.createEventProcess(crsEvent); if (eventProcess != null){ return eventProcess.execute(crsRequest); } return null;
這樣,程式碼就沒有了switch-case,增加一個事件也很簡單,只要實作EventProcess介面即可。
以上是Springboot中如何消除switch-case的詳細內容。更多資訊請關注PHP中文網其他相關文章!