在 Spring Boot 中,如何干掉 if else
不點藍字關注,我們哪來故事?

?正文如下?
來源:https://blog.csdn.net/hncu1306602liuqiang
看到crossover Jie的文章《利用策略模式優(yōu)化過多if else 代碼》后受到啟發(fā),可以利用策略模式簡化過多的if else代碼。
# 需求
這里虛擬一個業(yè)務需求,讓大家容易理解。假設有一個訂單系統(tǒng),里面的一個概念是根據(jù)訂單的不同類型做出不同的處理。
# 項目結構
訂單實體
/*** 訂單實體*/public class OrderDTO {private String code;private BigDecimal price;/** 訂單類型:* 1:普通訂單* 2:團購訂單* 3:促銷訂單*/private String type;//getter,setter自己實現(xiàn)}
service接口
/*** 訂單處理*/public interface IOrderService {/*** 根據(jù)訂單的不同類型做出不同的處理** @param dto 訂單實體* @return 為了簡單,返回字符串*/String orderHandler(OrderDTO dto);}//實現(xiàn)類1public class OrderServiceImpl implements IOrderService {public String orderHandler(OrderDTO dto) {if ("1".equals(dto.getType())) {//普通訂單處理} else if ("2".equals(dto.getType())) {//團購訂單處理} else if ("3".equals(dto.getType())) {//促銷訂單處理}//未來訂單類型增加}}//實現(xiàn)類二public class OrderServiceImpl implements IOrderService {//使用策略模式實現(xiàn)private HandlerContext handlerContext;public String orderHandler(OrderDTO dto) {/** 1:使用if..else實現(xiàn)* 2:使用策略模式實現(xiàn)*/AOrderTypeHandler instance = handlerContext.getInstance(dto.getType());return instance.handler(dto);}}
利用策略模式只需要2行代碼就可以搞定(也可以用工廠)
HandlerContext和HandlerProccessor/*** 訂單策略模式環(huán)境* 這個類的注入由HandlerProccessor實現(xiàn)*/public class HandlerContext {private Map<String, AOrderTypeHandler> handlerMap;/*** 構造傳參不能直接使用注解掃入*/public HandlerContext(Map<String, AOrderTypeHandler> handlerMap) {this.handlerMap = handlerMap;}/*** 獲得實例** @param type* @return*/public AOrderTypeHandler getInstance(String type) {if (type == null) {throw new IllegalArgumentException("type參數(shù)不能為空");}AOrderTypeHandler clazz = handlerMap.get(type);if (clazz == null) {throw new IllegalArgumentException("該類型沒有在枚舉OrderTypeHandlerAnno中定義,請定義:" + type);}return clazz;}}
/*** 策略模式,處理type與實現(xiàn)類的映射關系*/public class HandlerProccessor implements BeanFactoryPostProcessor {/*** 掃描@OrderTypeHandlerAnno注解,初始化HandlerContext,將其注冊到spring容器** @param beanFactory bean工廠* @throws BeansException*/public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {MaphandlerMap = new HashMap<>(); for (OrderTypeEnum temp : OrderTypeEnum.values()) {AOrderTypeHandler beanInstacle = getBeansWithAnnotation(beanFactory, AOrderTypeHandler.class, OrderTypeHandlerAnno.class, temp.getCode());handlerMap.put(temp.getCode(), beanInstacle);}HandlerContext context = new HandlerContext(handlerMap);//單例注入beanFactory.registerSingleton(HandlerContext.class.getName(), context);}/** 通過父類+注解找到實體類*/privateT getBeansWithAnnotation(ConfigurableListableBeanFactory beanFactory, Class manager, Class extends OrderTypeHandlerAnno> annotation, String code) throws BeansException {if (ObjectUtils.isEmpty(code)) {throw new RuntimeException("code is null ");}CollectiontCollection = beanFactory.getBeansOfType(manager).values(); for (T t : tCollection) {OrderTypeHandlerAnno orderTypeHandlerAnno = t.getClass().getAnnotation(annotation);if (ObjectUtils.isEmpty(orderTypeHandlerAnno)) {throw new RuntimeException("該注解沒有寫入值 :" + code);}//注解值是否與code相等if (code.equals(orderTypeHandlerAnno.value().getCode())) {return t;}}throw new RuntimeException("通過code沒有找到該注解對應的實體類 :" + code);}}
父抽象類+注解+枚舉
/*** 訂單類型處理定義* 使用抽象類,那么子類就只有一個繼承了*/public abstract class AOrderTypeHandler {/*** 一個訂單類型做一件事** @param dto 訂單實體* @return 為了簡單,返回字符串*/abstract public String handler(OrderDTO dto);}/*** 訂單類型注解* 使用方式:* 1:普通訂單 @OrderTypeHandlerAnno("1")* 2:團購訂單 @OrderTypeHandlerAnno("2")* 3:促銷訂單 @OrderTypeHandlerAnno("3")*/({ElementType.TYPE})(RetentionPolicy.RUNTIME)public OrderTypeHandlerAnno {OrderTypeEnum value();}/*** 訂單類型枚舉*/public enum OrderTypeEnum {Normal("1", "普通"),Group("2", "團隊"),Promotion("3", "促銷");private String code; //代碼private String name; //名稱,描述OrderTypeEnum(String code, String name) {this.code = code;this.name = name;}public String getCode() {return code;}public void setCode(String code) {this.code = code;}public String getName() {return name;}public void setName(String name) {this.name = name;}/*** 根據(jù)code屬性獲取name屬性** @param code* @return*/public static String getNameByCode(String code) {for (OrderTypeEnum temp : OrderTypeEnum.values()) {if (temp.getCode().equals(code)) {return temp.getName();}}return null;}}
業(yè)務人員實現(xiàn)類
//業(yè)務代碼/*** 普通訂單處理*/(OrderTypeEnum.Normal)public class NormalOrderHandler extends AOrderTypeHandler {public String handler(OrderDTO dto) {return "處理普通訂單";}}/*** 團隊訂單處理*/(OrderTypeEnum.Group)public class GroupOrderHandler extends AOrderTypeHandler {public String handler(OrderDTO dto) {return "處理團隊訂單";}}/*** 促銷訂單處理*/(OrderTypeEnum.Promotion)public class PromotionOrderHandler extends AOrderTypeHandler {public String handler(OrderDTO dto) {return "處理促銷訂單";}}
測試結果(使用chrome瀏覽器測試結果)



如果類型不存在

controller/*** 策略模式*/@RestControllerpublic class StrategyController {@Resource(name = "orderServiceImpl")private IOrderService orderService;@GetMapping("/api/order")@ResponseBodypublic String orderSave(OrderDTO dto) {String str = orderService.orderHandler(dto);return "{\"status\":1,\"msg\":\"保存成功\",\"data\":\"" + str + "\"}";}}pom.xml文檔"1.0" encoding="UTF-8"?><project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd"><modelVersion>4.0.0modelVersion><parent><groupId>org.springframework.bootgroupId><artifactId>spring-boot-starter-parentartifactId><version>2.2.1.RELEASEversion><relativePath/>parent><groupId>com.kayakgroupId><artifactId>study-designartifactId><version>0.0.1-SNAPSHOTversion><name>study-designname><description>Demo project for Spring Bootdescription><properties><java.version>1.8java.version>properties><dependencies><dependency><groupId>org.springframework.bootgroupId><artifactId>spring-boot-starter-webartifactId>dependency><dependency><groupId>org.springframework.bootgroupId><artifactId>spring-boot-starter-testartifactId><scope>testscope><exclusions><exclusion><groupId>org.junit.vintagegroupId><artifactId>junit-vintage-engineartifactId>exclusion>exclusions>dependency>dependencies><build><plugins><plugin><groupId>org.springframework.bootgroupId><artifactId>spring-boot-maven-pluginartifactId>plugin>plugins>build>project>
# 總結:
利用策略模式可以簡化復雜的if else代碼,方便維護,而利用自定義注解和自注冊的方式,可以方便應對需求的變更。
主要是方便了業(yè)務人員編寫代碼。

你好,來交個朋友 ~
往期推薦
↓ 或加泥瓦匠微信,交流更多技術?↓

評論
圖片
表情
