淺談?dòng)肧pringBoot實(shí)現(xiàn)策略模式
問(wèn)題的提出
閱讀別人代碼的時(shí)候最討厭遇到的就是大段大段的if-else分支語(yǔ)句,一般來(lái)說(shuō)讀到下面的時(shí)候就忘了上面在判斷什么了。很多資料上都會(huì)講到使用策略模式來(lái)改進(jìn)這種代碼邏輯。
策略模式的類(lèi)圖如下:

只需要按照這個(gè)圖寫(xiě)代碼就可以了。
策略模式代碼的實(shí)現(xiàn)
借助Spring框架我們能夠輕松的實(shí)現(xiàn)策略模式。
舉一個(gè)簡(jiǎn)單的例子,我們?nèi)タХ鹊曩I(mǎi)咖啡的時(shí)候,會(huì)根據(jù)自己的喜好和胃容量選擇大小杯。那么我們就要實(shí)現(xiàn)一個(gè)CoffeeStategy:
package com.example.demo.strategy;
public interface CoffeeStrategy {
void offer();
}
接下來(lái)就是各種具體策略的實(shí)現(xiàn)了,以中杯咖啡為例:
package com.example.demo.strategy;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
@Component("MID")
@Slf4j
public class MidCoffee implements CoffeeStrategy {
@Override
public void offer() {
log.info("你的中杯咖啡");
}
}
用Component注解給這個(gè)類(lèi)起一個(gè)名字叫做MID,這個(gè)在后面的應(yīng)用上下文中有起效。現(xiàn)在就開(kāi)始定義應(yīng)用上下文類(lèi):
package com.example.demo.strategy;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.Map;
@Service
public class CoffeeContext {
@Autowired
private Map<String, CoffeeStrategy> coffeeStrategyMap;
public void getCoffee(String size) {
this.coffeeStrategyMap.get(size).offer();
}
}
因?yàn)槭鞘褂昧薙pring框架,所有的Bean都被Spring自行管理,啟動(dòng)之后,Map中會(huì)有兩個(gè)元素:{"MID":MidCoffee}和{"LARGE":LargeCoffee}。在具體的業(yè)務(wù)邏輯中,只需要引入應(yīng)用上下文類(lèi),每次使用getCoffee方法就可以了。
比如這個(gè)Controller方法:
@GetMapping("/get")
public void getCoffee(@Param("size") String size) {
this.coffeeContext.getCoffee(size);
}
請(qǐng)求這個(gè)接口,我們能在后臺(tái)看到具體的日志內(nèi)容:
2021-09-30 22:46:32.550 INFO 15628 --- [nio-8099-exec-1] com.example.demo.strategy.LargeCoffee : 您的大杯咖啡
2021-09-30 22:46:39.201 INFO 15628 --- [nio-8099-exec-7] com.example.demo.strategy.LargeCoffee : 您的大杯咖啡
進(jìn)一步的思考
之前寫(xiě)過(guò)Component中起的名字有奇效。如果我們沒(méi)有用Spring框架去實(shí)現(xiàn)策略模式,那么我們的代碼要如何編寫(xiě)呢?
首先可以肯定的是策略接口和策略實(shí)現(xiàn)類(lèi)是不需要變的。需要變的地方就是應(yīng)用上下文了,因?yàn)椴淮嬖谧詣?dòng)注入了。這段代碼就會(huì)變成大致這樣:
package com.example.demo.strategy;
public class CoffeeContext {
CoffeeStrategy coffeeStrategy;
public CoffeeContext(CoffeeStrategy coffeeStrategy) {
this.coffeeStrategy = coffeeStrategy;
}
public void getCoffee() {
this.coffeeStrategy.offer();
}
}
這樣,在實(shí)際使用的時(shí)候,我需要先新建一個(gè)具體的實(shí)現(xiàn)類(lèi)對(duì)象,然后將這個(gè)對(duì)象傳入策略應(yīng)用上下文去。這種方式怎么看著都沒(méi)有Spring的實(shí)現(xiàn)方式優(yōu)雅。
CoffeeStrategy mid = new MidCoffee(); CoffeeContext context = new CoffeeContext(mid); context.getCoffee();
在我實(shí)際改造代碼的過(guò)程中我發(fā)現(xiàn)有些策略其實(shí)是一樣的,只是個(gè)別參數(shù)不同罷了。我對(duì)接的是各個(gè)業(yè)務(wù)供應(yīng)商,有些供應(yīng)商的接口邏輯式樣的,只是URL和USERNAME不一樣罷了。于是好幾個(gè)策略實(shí)現(xiàn)類(lèi)的代碼重復(fù)很?chē)?yán)重,這個(gè)時(shí)候我使用了Java8開(kāi)始提供的接口default方法。這種方法的好處就是能將這種一樣的邏輯提取到interface中,只要實(shí)現(xiàn)類(lèi)不重寫(xiě),那么就會(huì)默認(rèn)使用default方法。
這樣改造之后,我的代碼又精簡(jiǎn)了很多。
心得體會(huì)
在我接手現(xiàn)在這個(gè)項(xiàng)目代碼的時(shí)候,之前的程序員將代碼寫(xiě)的很直白,就是可以不用任何的設(shè)計(jì),直接寫(xiě)邏輯。這也沒(méi)錯(cuò),可是用IDEA的時(shí)候會(huì)各種提示重復(fù)代碼啊之類(lèi)的,讓人看著不開(kāi)心。而且還有大量的if-else分支讓人摸不著頭腦。
在我大刀闊斧的改造之后,代碼行數(shù)越來(lái)越少,但是可讀性卻越來(lái)越高。
此時(shí)我是比較理解GoF在設(shè)計(jì)模式這本書(shū)里提到的一句話(huà),大致意思就是開(kāi)發(fā)一個(gè)面向?qū)ο蟮某绦虿⒉缓?jiǎn)單。
到此這篇關(guān)于淺談?dòng)肧pringBoot實(shí)現(xiàn)策略模式的文章就介紹到這了,更多相關(guān)SpringBoot 策略模式內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
詳細(xì)聊聊SpringBoot中動(dòng)態(tài)切換數(shù)據(jù)源的方法
在大型分布式項(xiàng)目中,經(jīng)常會(huì)出現(xiàn)多數(shù)據(jù)源的情況,下面這篇文章主要給大家介紹了關(guān)于SpringBoot中動(dòng)態(tài)切換數(shù)據(jù)源的相關(guān)資料,文中通過(guò)示例代碼介紹的非常詳細(xì),需要的朋友可以參考下2021-09-09
Java異常簡(jiǎn)介和架構(gòu)_動(dòng)力節(jié)點(diǎn)Java學(xué)院整理
這篇文章主要分享了Java異常簡(jiǎn)介和架構(gòu),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2017-06-06
mybatis plus實(shí)體類(lèi)中字段映射mysql中的json格式方式
這篇文章主要介紹了mybatis plus實(shí)體類(lèi)中字段映射mysql中的json格式方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2021-08-08
SpringBoot 統(tǒng)一請(qǐng)求返回的實(shí)現(xiàn)
這篇文章主要介紹了SpringBoot 統(tǒng)一請(qǐng)求返回的實(shí)現(xiàn),文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2020-07-07
Mybatis的Mapper代理對(duì)象生成及調(diào)用過(guò)程示例詳解
這篇文章主要為大家介紹了Mybatis的Mapper代理對(duì)象生成及調(diào)用過(guò)程示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-09-09
使用Java開(kāi)發(fā)實(shí)現(xiàn)OAuth安全認(rèn)證的應(yīng)用
這篇文章主要介紹了使用Java開(kāi)發(fā)實(shí)現(xiàn)OAuth安全認(rèn)證的應(yīng)用的方法,OAuth安全認(rèn)證經(jīng)常出現(xiàn)于社交網(wǎng)絡(luò)API應(yīng)用的相關(guān)開(kāi)發(fā)中,需要的朋友可以參考下2015-11-11
java編程創(chuàng)建型設(shè)計(jì)模式單例模式的七種示例
這篇文章主要為大家介紹了java編程中創(chuàng)建型設(shè)計(jì)模式之單例模式的示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助2022-02-02
IDEA導(dǎo)入Springboot項(xiàng)目,注解和pom文件不識(shí)別的解決
這篇文章主要介紹了IDEA導(dǎo)入Springboot項(xiàng)目,注解和pom文件不識(shí)別的解決方案,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2023-04-04

