## springboot 下策略模式的簡單使用
1.靈魂三問
接手前人(已跑路)專案快樂否?
- 前人專案不寫註釋懵逼否?
一個方法中一堆if/else,且業務判斷條件用簡單數字(或英文字母),不帶註釋,想打人否?
所以,對於上述三個問題,我寫了此隨筆,然而————然並卵
這篇文章並不能讓你不接手前人專案,並不能讓你看懂沒有註釋的業務程式碼,也並不能讓你以後不碰到if/else轟擊波,但是——系尬系
魯迅先生曾倡導過,如果你覺得政府腐敗,那麼你就應該努力考取公務員從政,去內部解決腐敗;如果你覺得你的家鄉建設不夠美麗,那麼你應該去建設他;如果你覺得人民素質不夠高,那麼你應該提高自身素質,以身作則;如果你覺得這功能完全是業務無理取鬧,產品瞎接,那麼你應該——好吧,業務爸爸一切都好。
瞎扯了半天,下面進入正題:
很多情況下,都沒有一次到位得產品,也通常沒有一次到位的業務需求,所以在後期的功能擴充套件中,很可能會造成不停的對原始碼加入if/else分支判斷,來滿足新的業務需求,然而這對於後接手的程式設計師來說,在一堆if/else,幾百行程式碼中去快速理解邏輯,並加入擴充套件,無疑是件很蛋疼的事(好吧,其實我的真實原因是:看起來有點醜),所以,如何改造自己的if/else程式碼,讓其看的不顯臃腫,直觀簡潔,我百度了一下,簡單寫了份在springboot
環境下,利用策略模式改造程式碼的隨筆,作為新知識的get體會!(好吧,策略模式其實很常見)
2.什麼是策略模式
策略模式(Strategy Pattern):一個類的行為或其演算法可以在執行時更改。這種型別的設計模式屬於行為型模式。
執行時隨時更改,有沒有想到spring的自動注入?靈活,易擴充套件這也是其特點之一。有沒有具體的實現步驟呢?有的!
3.簡單實現步驟
簡單的一個需求
首先,先假想一個簡單的業務——新需求上,這個功能暫時有三個分支判斷,三個分支對應不同的執行邏輯:
- 1——孫悟空邏輯
- 2——二師兄邏輯
- 3——唐僧邏輯
那麼,首先,我們當然可以用if/else,switch,來做分支判斷解決,好的解決,專案上線,後期擴充套件——
業務A有發話了,我覺得應該有4——沙師弟邏輯,對吧,是這樣吧!好,我再加一個if,沒問題的!
業務B突然有話發話了,我覺得應該有5——三隻眼邏輯,對吧,不能沒有二郎神啊!好,我再加一個if,
ojbk
- 業務C突然有想法了,咋不能忘了6——小白馬吧,對吧,這麼辛苦!嗯~~~,可以,應該可以快速實現!
業務D又來了,我覺得那白骨精挺漂亮的,是吧?你(漂亮你大爺)!!!!!!!好,還有沒有漂亮的?
所以,這個分支的類,看起來有點難受!
策略模式實現步驟
好的話不多說,策略模式下,我們可以怎麼解決這個問題呢?
- 首先,可以建立一個列舉類,用於儲存分支判斷的條件(也可以用靜態變數)
public enum WestCommand {
W_SuWuKong(1,"孫爺爺","monkeyCommand"),
W_ZhuBaJie(2,"二師兄","pigCommand"),
W_TangSeng(3,"和尚","monkCommand");
private int value;
private String descreption;
private String beanName;
private WestCommand(int value,String descreption,String beanName){
this.value=value;
this.descreption=descreption;
this.beanName=beanName;
}
public int getValue(){
return value;
}
public String getDescreption(){
return descreption;
}
public String getBeanName(){
return beanName;
}
public static WestCommand getInstance(int value) {
for(WestCommand type : WestCommand.values()) {
if(type.getValue() == value) {
return type;
}
}
return null;
}
}
這個類用於儲存分支判斷條件,,,,,
- 建立策略角色介面
/**
* @說明:
* @型別名稱:StrategyCommand
* @建立者: Raiden
* @建立時間: 2020/2/11 12:01
* @修改者: Raiden
* @修改時間: 2020/2/11 12:01
*/
public interface StrategyCommand {
String process();
}
- 建立具體策略角色
/**
* @說明:唐僧
* @型別名稱:MonkeyCommand
* @建立者: Raiden
* @建立時間: 2020/2/11 12:02
* @修改者: Raiden
* @修改時間: 2020/2/11 12:02
*/
@Service
public class MonkCommand implements StrategyCommand {
@Override
public String process() {
return "和尚不曾調戲妖精了,施主還是別問了!!";
}
}
/**
* @說明:孫悟空
* @型別名稱:MonkeyCommand
* @建立者: Raiden
* @建立時間: 2020/2/11 12:02
* @修改者: Raiden
* @修改時間: 2020/2/11 12:02
*/
@Service
public class MonkeyCommand implements StrategyCommand {
@Override
public String process() {
return "你孫爺爺叫你回家吃飯了!!";
}
}
/**
* @說明:二師兄
* @型別名稱:MonkeyCommand
* @建立者: Raiden
* @建立時間: 2020/2/11 12:02
* @修改者: Raiden
* @修改時間: 2020/2/11 12:02
*/
@Service
public class PigCommand implements StrategyCommand {
@Override
public String process() {
return "你二師兄走位相當風騷!!";
}
}
- 建立上下文,獲取具體角色
這裡首先需要建立一個spring的工具類,用於根據id獲取bean
/**
* @說明:
* @型別名稱:StrategeContext
* @建立者: Raiden
* @建立時間: 2020/2/11 14:41
* @修改者: Raiden
* @修改時間: 2020/2/11 14:41
*/
@Component
public class SpringUtils implements ApplicationContextAware {
private static ApplicationContext context;
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
if (SpringUtils.context==null){
SpringUtils.context=applicationContext;
System.out.println("初始化容器成功------------");
}
}
//獲取context
public static ApplicationContext getContext(){
return SpringUtils.context;
}
//通過名稱獲取bean
public static Object getBean(String beanName){
return getContext().getBean(beanName);
}
/**
* 通過型別獲取bean
* @param tClass
* @param <T>
* @return
*/
public static <T> T getBean(Class<T> tClass){
return getContext().getBean(tClass);
}
public static <T> T getBean(String beanName,Class<T> classType){
return getContext().getBean(beanName,classType);
}
}
然後,建立上下文
/**
* @說明:
* @型別名稱:StrategyContext
* @建立者: Raiden
* @建立時間: 2020/2/11 15:05
* @修改者: Raiden
* @修改時間: 2020/2/11 15:05
*/
public class StrategyContext {
/**
* 獲取對應的command實現類
* @param value
* @param classType
* @param <T>
* @return
*/
public static <T> T getStrategyBean(Integer value,Class<T> classType){
return SpringUtils.getBean(
WestCommand.getInstance(value).getBeanName(),classType);
}
}
在這裡,一切準備工作基本算是完成了,下面,我們來看看效果
這裡我是利用的springboot+springcloud
建立了一個介面:
相應的控制層:
/**
* @說明:
* @型別名稱:StrategyCrtl
* @建立者: Raiden
* @建立時間: 2020/2/11 11:58
* @修改者: Raiden
* @修改時間: 2020/2/11 11:58
*/
@RestController
@RequestMapping("/strategy")
public class StrategyCrtl {
@GetMapping("/{number}")
public ResponseEntity<String> getMessage(@PathVariable Integer number){
StrategyCommand bean = StrategyContext.getStrategyBean(number, StrategyCommand.class);
return ResponseEntity.ok(bean.process());
}
}
業務邏輯幹掉了if/else,啟動服務:
我們看一看看效果:1——孫悟空邏輯
2——二師兄邏輯
3——和尚邏輯