在 Spring Boot 中,如何干掉 if else 呢?
原文鏈接:https://blog.csdn.net/hncu1306602liuqiang
需求
這里虛擬一個(gè)業(yè)務(wù)需求,讓大家容易理解。假設(shè)有一個(gè)訂單系統(tǒng),里面的一個(gè)概念是根據(jù)訂單的不同類型做出不同的處理。
項(xiàng)目結(jié)構(gòu)

訂單實(shí)體
/**
?*?訂單實(shí)體
?*/
public?class?OrderDTO?{
????private?String?code;
????private?BigDecimal?price;
????/*
?????*?訂單類型:
?????* 1:普通訂單
?????* 2:團(tuán)購(gòu)訂單
?????* 3:促銷訂單
?????*/
????private?String?type;
//getter,setter自己實(shí)現(xiàn)
}
service接口
/**
?*?訂單處理
?*/
public?interface?IOrderService?{
????/**
?????*?根據(jù)訂單的不同類型做出不同的處理
?????*
?????*?@param?dto?訂單實(shí)體
?????*?@return?為了簡(jiǎn)單,返回字符串
?????*/
????String?orderHandler(OrderDTO?dto);
}
//實(shí)現(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()))?{
????????????//團(tuán)購(gòu)訂單處理
????????}?else?if?("3".equals(dto.getType()))?{
????????????//促銷訂單處理
????????}
????????//未來(lái)訂單類型增加
????}
}
//實(shí)現(xiàn)類二
@Component
public?class?OrderServiceImpl?implements?IOrderService?{
????//使用策略模式實(shí)現(xiàn)
????@Autowired
????private?HandlerContext?handlerContext;
????@Override
????public?String?orderHandler(OrderDTO?dto)?{
????????/*
?????????* 1:使用if..else實(shí)現(xiàn)
?????????* 2:使用策略模式實(shí)現(xiàn)
?????????*/
????????AOrderTypeHandler?instance?=?handlerContext.getInstance(dto.getType());
????????return?instance.handler(dto);
????}
}
利用策略模式只需要2行代碼就可以搞定(也可以用工廠)
HandlerContext和HandlerProccessor
/**
?*?訂單策略模式環(huán)境
?*?這個(gè)類的注入由HandlerProccessor實(shí)現(xiàn)
?*/
public?class?HandlerContext?{
????private?Map?handlerMap;
????/**
?????*?構(gòu)造傳參不能直接使用注解掃入
?????*/
????public?HandlerContext(Map?handlerMap )?{
????????this.handlerMap?=?handlerMap;
????}
????/**
?????*?獲得實(shí)例
?????*
?????*?@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("該類型沒(méi)有在枚舉OrderTypeHandlerAnno中定義,請(qǐng)定義:"?+?type);
????????}
????????return?clazz;
????}
}
/**
?*?策略模式,處理type與實(shí)現(xiàn)類的映射關(guān)系
?*/
@Component
public?class?HandlerProccessor?implements?BeanFactoryPostProcessor?{
????/**
?????*?掃描@OrderTypeHandlerAnno注解,初始化HandlerContext,將其注冊(cè)到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);
????}
????/*
?????*?通過(guò)父類+注解找到實(shí)體類
?????*/
????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("該注解沒(méi)有寫(xiě)入值?:"?+?code);
????????????}
????????????//注解值是否與code相等
????????????if?(code.equals(orderTypeHandlerAnno.value().getCode()))?{
????????????????return?t;
????????????}
????????}
????????throw?new?RuntimeException("通過(guò)code沒(méi)有找到該注解對(duì)應(yīng)的實(shí)體類?:"?+?code);
????}
}
父抽象類+注解+枚舉
/**
?*?訂單類型處理定義
?*?使用抽象類,那么子類就只有一個(gè)繼承了
?*/
public?abstract?class?AOrderTypeHandler?{
????/**
?????*?一個(gè)訂單類型做一件事
?????*
?????*?@param?dto?訂單實(shí)體
?????*?@return?為了簡(jiǎn)單,返回字符串
?????*/
????abstract?public?String?handler(OrderDTO?dto);
}
/**
?*?訂單類型注解
?*?使用方式:
?* 1:普通訂單?@OrderTypeHandlerAnno("1")
?* 2:團(tuán)購(gòu)訂單?@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",?"團(tuán)隊(duì)"),
????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ù)人員實(shí)現(xiàn)類
//業(yè)務(wù)代碼
/**
?*?普通訂單處理
?*/
@Component
@OrderTypeHandlerAnno(OrderTypeEnum.Normal)
public?class?NormalOrderHandler?extends?AOrderTypeHandler?{
????@Override
????public?String?handler(OrderDTO?dto)?{
????????return?"處理普通訂單";
????}
}
/**
?*?團(tuán)隊(duì)訂單處理
?*/
@Component
@OrderTypeHandlerAnno(OrderTypeEnum.Group)
public?class?GroupOrderHandler?extends?AOrderTypeHandler?{
????@Override
????public?String?handler(OrderDTO?dto)?{
????????return?"處理團(tuán)隊(duì)訂單";
????}
}
/**
?*?促銷訂單處理
?*/
@Component
@OrderTypeHandlerAnno(OrderTypeEnum.Promotion)
public?class?PromotionOrderHandler?extends?AOrderTypeHandler?{
????@Override
????public?String?handler(OrderDTO?dto)?{
????????return?"處理促銷訂單";
????}
}
測(cè)試結(jié)果(使用chrome瀏覽器測(cè)試結(jié)果)



如果類型不存在

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é):
利用策略模式可以簡(jiǎn)化復(fù)雜的if else代碼,方便維護(hù),而利用自定義注解和自注冊(cè)的方式,可以方便應(yīng)對(duì)需求的變更。
主要是方便了業(yè)務(wù)人員編寫(xiě)代碼。
這個(gè)就是個(gè)人筆記,不喜勿噴。
?關(guān)注公眾號(hào):Java后端編程,回復(fù)下面關(guān)鍵字?
要Java學(xué)習(xí)完整路線,回復(fù)??路線?
缺Java入門(mén)視頻,回復(fù):?視頻?
要Java面試經(jīng)驗(yàn),回復(fù)??面試?
缺Java項(xiàng)目,回復(fù):?項(xiàng)目?
進(jìn)Java粉絲群:?加群?
PS:如果覺(jué)得我的分享不錯(cuò),歡迎大家隨手點(diǎn)贊、在看。
(完) 加我"微信"?獲取一份 最新Java面試題資料 請(qǐng)備注:666,不然不通過(guò)~
最近好文
1、Kafka 3.0重磅發(fā)布,棄用 Java 8 的支持!
最近面試BAT,整理一份面試資料《Java面試BAT通關(guān)手冊(cè)》,覆蓋了Java核心技術(shù)、JVM、Java并發(fā)、SSM、微服務(wù)、數(shù)據(jù)庫(kù)、數(shù)據(jù)結(jié)構(gòu)等等。 獲取方式:關(guān)注公眾號(hào)并回復(fù)?java?領(lǐng)取,更多內(nèi)容陸續(xù)奉上。 明天見(jiàn)(??ω??)??
評(píng)論
圖片
表情
