在 Spring Boot 中,如何幹掉 if else

原文連結:https://blog。csdn。net/hncu1306602liuqiang

看到crossover Jie的文章《利用策略模式最佳化過多if else 程式碼》後受到啟發,可以利用策略模式簡化過多的if else程式碼。

需求

這裡虛擬一個業務需求,讓大家容易理解。假設有一個訂單系統,裡面的一個概念是根據訂單的不同型別做出不同的處理。

專案結構

在 Spring Boot 中,如何幹掉 if else

訂單實體

/**

* 訂單實體

*/

public

class

OrderDTO

{

private

String code;

private

BigDecimal price;

/*

* 訂單型別:

* 1:普通訂單

* 2:團購訂單

* 3:促銷訂單

*/

private

String type;

//getter,setter自己實現

}

service介面

/**

* 訂單處理

*/

public

interface

IOrderService

{

/**

* 根據訂單的不同型別做出不同的處理

*

*

@param

dto 訂單實體

*

@return

為了簡單,返回字串

*/

String

orderHandler

(OrderDTO dto)

}

//實現類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())) {

//促銷訂單處理

}

//未來訂單型別增加

}

}

//實現類二

@Component

public

class

OrderServiceImpl

implements

IOrderService

{

//使用策略模式實現

@Autowired

private

HandlerContext handlerContext;

@Override

public

String

orderHandler

(OrderDTO dto)

{

/*

* 1:使用if。。else實現

* 2:使用策略模式實現

*/

AOrderTypeHandler instance = handlerContext。getInstance(dto。getType());

return

instance。handler(dto);

}

}

利用策略模式只需要2行程式碼就可以搞定(也可以用工廠)

HandlerContext和HandlerProccessor

/**

* 訂單策略模式環境

* 這個類的注入由HandlerProccessor實現

*/

public

class

HandlerContext

{

private

Map handlerMap;

/**

* 構造傳參不能直接使用註解掃入

*/

public

HandlerContext

Map handlerMap

{

this

。handlerMap = handlerMap;

}

/**

* 獲得例項

*

* @param type

* @return

*/

public

AOrderTypeHandler

getInstance

String type

{

if

(type ==

null

) {

throw

new

IllegalArgumentException(

“type引數不能為空”

);

}

AOrderTypeHandler clazz = handlerMap。

get

(type);

if

(clazz ==

null

) {

throw

new

IllegalArgumentException(

“該型別沒有在列舉OrderTypeHandlerAnno中定義,請定義:”

+ type);

}

return

clazz;

}

}

/**

* 策略模式,處理type與實現類的對映關係

*/

@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沒有找到該註解對應的實體類 :”

+ 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;

}

/**

* 根據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

}

}

業務人員實現類

//業務程式碼

/**

* 普通訂單處理

*/

@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

“處理促銷訂單”

}

}

測試結果(使用chrome瀏覽器測試結果)

在 Spring Boot 中,如何幹掉 if else

在 Spring Boot 中,如何幹掉 if else

在 Spring Boot 中,如何幹掉 if else

如果型別不存在

在 Spring Boot 中,如何幹掉 if else

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文件

<?xml version=

“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。0

modelVersion

>

<

parent

>

<

groupId

>

org。springframework。boot

groupId

>

<

artifactId

>

spring-boot-starter-parent

artifactId

>

<

version

>

2。2。1。RELEASE

version

>

<

relativePath

/>

<!—— lookup parent from repository ——>

parent

>

<

groupId

>

com。kayak

groupId

>

<

artifactId

>

study-design

artifactId

>

<

version

>

0。0。1-SNAPSHOT

version

>

<

name

>

study-design

name

>

<

description

>

Demo project for Spring Boot

description

>

<

properties

>

<

java。version

>

1。8

java。version

>

properties

>

<

dependencies

>

<

dependency

>

<

groupId

>

org。springframework。boot

groupId

>

<

artifactId

>

spring-boot-starter-web

artifactId

>

dependency

>

<

dependency

>

<

groupId

>

org。springframework。boot

groupId

>

<

artifactId

>

spring-boot-starter-test

artifactId

>

<

scope

>

test

scope

>

<

exclusions

>

<

exclusion

>

<

groupId

>

org。junit。vintage

groupId

>

<

artifactId

>

junit-vintage-engine

artifactId

>

exclusion

>

exclusions

>

dependency

>

dependencies

>

<

build

>

<

plugins

>

<

plugin

>

<

groupId

>

org。springframework。boot

groupId

>

<

artifactId

>

spring-boot-maven-plugin

artifactId

>

plugin

>

plugins

>

build

>

project

>

總結:

利用策略模式可以簡化複雜的if else程式碼,方便維護,而利用自定義註解和自注冊的方式,可以方便應對需求的變更。

主要是方便了業務人員編寫程式碼。

這個就是個人筆記,不喜勿噴。