在 Spring Boot 中,如何干掉 if else
AI全套:Python3+TensorFlow打造人臉識別智能小程序
最新人工智能資料-Google工程師親授 Tensorflow-入門到進階
黑馬頭條項目 - Java Springboot2.0(視頻、資料、代碼和講義)14天完整版
看到crossover Jie的文章《利用策略模式優(yōu)化過多if else 代碼》后受到啟發(fā),可以利用策略模式簡化過多的if else代碼。
需求
這里虛擬一個業(yè)務(wù)需求,讓大家容易理解。假設(shè)有一個訂單系統(tǒng),里面的一個概念是根據(jù)訂單的不同類型做出不同的處理。
項目結(jié)構(gòu)

訂單實體
/**
?*?訂單實體
?*/
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)類1
@Component
public?class?OrderServiceImpl?implements?IOrderService?{
????@Override
????public?String?orderHandler(OrderDTO?dto)?{
????????if?("1".equals(dto.getType()))?{
????????????//普通訂單處理
????????}?else?if?("2".equals(dto.getType()))?{
????????????//團購訂單處理
????????}?else?if?("3".equals(dto.getType()))?{
????????????//促銷訂單處理
????????}
????????//未來訂單類型增加
????}
}
//實現(xiàn)類二
@Component
public?class?OrderServiceImpl?implements?IOrderService?{
????//使用策略模式實現(xiàn)
????@Autowired
????private?HandlerContext?handlerContext;
????@Override
????public?String?orderHandler(OrderDTO?dto)?{
????????/*
?????????* 1:使用if..else實現(xiàn)
?????????* 2:使用策略模式實現(xiàn)
?????????*/
????????AOrderTypeHandler?instance?=?handlerContext.getInstance(dto.getType());
????????return?instance.handler(dto);
????}
}
HandlerContext和HandlerProccessor
/**
?*?訂單策略模式環(huán)境
?*?這個類的注入由HandlerProccessor實現(xiàn)
?*/
public?class?HandlerContext?{
????private?Map?handlerMap;
????/**
?????*?構(gòu)造傳參不能直接使用注解掃入
?????*/
????public?HandlerContext(Map?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)類的映射關(guān)系
?*/
@Component
public?class?HandlerProccessor?implements?BeanFactoryPostProcessor?{
????/**
?????*?掃描@OrderTypeHandlerAnno注解,初始化HandlerContext,將其注冊到spring容器
?????*
?????*?@param?beanFactory?bean工廠
?????*?@throws?BeansException
?????*/
????@Override
????public?void?postProcessBeanFactory(ConfigurableListableBeanFactory?beanFactory)?throws?BeansException?{
????????Map?handlerMap?=?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);
????}
????/*
?????*?通過父類+注解找到實體類
?????*/
????private??T?getBeansWithAnnotation(ConfigurableListableBeanFactory?beanFactory,?Class?manager,?Class?extends?OrderTypeHandlerAnno>?annotation,?String?code) ?throws?BeansException?{
????????if?(ObjectUtils.isEmpty(code))?{
????????????throw?new?RuntimeException("code?is?null?");
????????}
????????Collection?tCollection?=?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沒有找到該注解對應(yīng)的實體類?:"?+?code);
????}
}
父抽象類+注解+枚舉
/**
?*?訂單類型處理定義
?*?使用抽象類,那么子類就只有一個繼承了
?*/
public?abstract?class?AOrderTypeHandler?{
????/**
?????*?一個訂單類型做一件事
?????*
?????*?@param?dto?訂單實體
?????*?@return?為了簡單,返回字符串
?????*/
????abstract?public?String?handler(OrderDTO?dto);
}
/**
?*?訂單類型注解
?*?使用方式:
?* 1:普通訂單?@OrderTypeHandlerAnno("1")
?* 2:團購訂單?@OrderTypeHandlerAnno("2")
?* 3:促銷訂單?@OrderTypeHandlerAnno("3")
?*/
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
public?@interface?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è)務(wù)代碼
/**
?*?普通訂單處理
?*/
@Component
@OrderTypeHandlerAnno(OrderTypeEnum.Normal)
public?class?NormalOrderHandler?extends?AOrderTypeHandler?{
????@Override
????public?String?handler(OrderDTO?dto)?{
????????return?"處理普通訂單";
????}
}
/**
?*?團隊訂單處理
?*/
@Component
@OrderTypeHandlerAnno(OrderTypeEnum.Group)
public?class?GroupOrderHandler?extends?AOrderTypeHandler?{
????@Override
????public?String?handler(OrderDTO?dto)?{
????????return?"處理團隊訂單";
????}
}
/**
?*?促銷訂單處理
?*/
@Component
@OrderTypeHandlerAnno(OrderTypeEnum.Promotion)
public?class?PromotionOrderHandler?extends?AOrderTypeHandler?{
????@Override
????public?String?handler(OrderDTO?dto)?{
????????return?"處理促銷訂單";
????}
}
測試結(jié)果(使用chrome瀏覽器測試結(jié)果)




????4.0.0 ????????????org.springframework.boot ????????spring-boot-starter-parent ????????2.2.1.RELEASE ???????? ????? ????com.kayak ????study-design ????0.0.1-SNAPSHOT ????study-design ????Demo?project?for?Spring?Boot ????????????1.8 ???? ????????????????????????org.springframework.boot ????????????spring-boot-starter-web ???????? ????????????????????org.springframework.boot ????????????spring-boot-starter-test ????????????test ????????????????????????????????????????????????org.junit.vintage ????????????????????junit-vintage-engine ???????????????? ???????????? ???????? ???? ????????????????????????????????????????org.springframework.boot ????????????????spring-boot-maven-plugin ???????????? ???????? ???? " tab="innerlink" data-linktype="2" wah-hotarea="click" style="outline: 0px; -webkit-tap-highlight-color: rgba(0, 0, 0, 0); cursor: pointer; max-width: 100%; box-sizing: border-box !important; overflow-wrap: break-word !important;">controller
/**
?*?策略模式
?*/
@RestController
public?class?StrategyController?{
????@Resource(name?=?"orderServiceImpl")
????private?IOrderService?orderService;
????@GetMapping("/api/order")
????@ResponseBody
????public?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>總結(jié):
利用策略模式可以簡化復(fù)雜的if else代碼,方便維護,而利用自定義注解和自注冊的方式,可以方便應(yīng)對需求的變更。
全棧架構(gòu)社區(qū)交流群
?「全棧架構(gòu)社區(qū)」建立了讀者架構(gòu)師交流群,大家可以添加小編微信進行加群。歡迎有想法、樂于分享的朋友們一起交流學(xué)習(xí)。
看完本文有收獲?請轉(zhuǎn)發(fā)分享給更多人
往期資源:
評論
圖片
表情
