原文連結:https://blog。csdn。net/hncu1306602liuqiang
看到crossover Jie的文章《利用策略模式最佳化過多if else 程式碼》後受到啟發,可以利用策略模式簡化過多的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
/**
* 構造傳參不能直接使用註解掃入
*/
public
HandlerContext
(
Map
)
{
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
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
throws
BeansException
{
if
(ObjectUtils。isEmpty(code)) {
throw
new
RuntimeException(
“code is null ”
);
}
Collection
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瀏覽器測試結果)
如果型別不存在
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程式碼,方便維護,而利用自定義註解和自注冊的方式,可以方便應對需求的變更。
主要是方便了業務人員編寫程式碼。
這個就是個人筆記,不喜勿噴。