1. 程式人生 > 其它 >策略模式 if else_使用列舉+工廠模式+策略模式去掉多重if...else

策略模式 if else_使用列舉+工廠模式+策略模式去掉多重if...else

技術標籤:策略模式 if else策略模式和工廠模式的區別

現實生活中,我們進經常會遇到滿減活動或者打折活動,同一個促銷活動可能後不同的策略,比如滿30減5,滿200打8折......用程式來實現的話,可以使用工廠設計模式+策略設計模式

01

工廠設計模式

這種型別的設計模式屬於建立型模式,它提供了一種建立物件的最佳方式。
在工廠模式中,我們在建立物件時不會對客戶端暴露建立邏輯,
並且是通過使用一個共同的介面來指向新建立的物件。
您需要一輛汽車,可以直接從工廠裡面提貨,
而不用去管這輛汽車是怎麼做出來的,以及這個汽車裡面的具體實現

優點:
1、一個呼叫者想建立一個物件,只要知道其名稱就可以了。
2、擴充套件性高,如果想增加一個產品,只要擴充套件一個工廠類就可以。
3、遮蔽產品的具體實現,呼叫者只關心產品的介面。

缺點:每次增加一個產品時,都需要增加一個具體類和物件實現工廠,
使得系統中類的個數成倍增加,在一定程度上增加了系統的複雜度,
同時也增加了系統具體類的依賴。這並不是什麼好事。

02

策略設計模式

一個類的行為或其演算法可以在執行時更改。這種型別的設計模式屬於行為型模式
意圖:定義一系列的演算法,把它們一個個封裝起來, 並且使它們可相互替換。
主要解決:在有多種演算法相似的情況下,使用 if...else所帶來的複雜和難以維護
何時使用:一個系統有許多許多類,而區分它們的只是他們直接的行為。
如何解決:將這些演算法封裝成一個一個的類,任意地替換。
優點:
1、演算法可以自由切換。
2、避免使用多重條件判斷。
3、擴充套件性良好。
缺點:
1、策略類會增多。
2、所有策略類都需要對外暴露。
使用場景:
1、如果在一個系統裡面有許多類,它們之間的區別僅在於它們的行為,
那麼使用策略模式可以動態地讓一個物件在許多行為中選擇一種行為。
2、一個系統需要動態地在幾種演算法中選擇一種。
3、如果一個物件有很多的行為,如果不用恰當的模式,
這些行為就只好使用多重的條件選擇語句來實現。

注意事項:如果一個系統的策略多於四個,
就需要考慮使用混合模式,解決策略類膨脹的問題

03

實戰

//活動策略介面
interfaceActivityStrategy{
//獲取折扣後的金額方法
BigDecimal getDiscount(BigDecimal amount);
//根據型別獲取具體活動策略物件
//根據它來去掉多重if-else,當然引入列舉後,該方法可以去掉
String getType();
}
//滿30減5活動策略--具體實現類
classFull30Minus5ActivityStrategyimplementsActivityStrategy{
@Override
publicBigDecimal getDiscount(BigDecimal amount){
returnamount.subtract(BigDecimal.valueOf(5d)).setScale(2);
}
@Override
publicString getType(){
returnFull30Minus5ActivityStrategy.class.getName();
}
}
//滿200打8折活動策略--具體實現類
classFull200Discount8ActivityStrategyimplementsActivityStrategy{
@Override
publicBigDecimal getDiscount(BigDecimal amount){
returnamount.multiply(BigDecimal.valueOf(0.8d)).setScale(2);
}
@Override
publicString getType(){
returnFull200Discount8ActivityStrategy.class.getName();
}
}
/**
* 活動策略工廠
*/
classActivityStrategyFactory{
//靜態內部類
publicstaticclassHolder{
publicstaticActivityStrategyFactory instance = newActivityStrategyFactory();
}
//提供公有方法對外進行訪問
publicstaticActivityStrategyFactory getInstance() {
returnHolder.instance;
}
//私有建構函式,提供單例工廠
privateActivityStrategyFactory() {
}
//根據型別,通過反射獲取具體活動策略物件
publicActivityStrategy getActivityStrategy(String type) {
try{
Objects.requireNonNull(type);//非空判斷
return(ActivityStrategy) Class.forName(type).newInstance();
}catch(ClassNotFoundException | InstantiationException | IllegalAccessException e) {
e.printStackTrace();
}
returnnull;
}
}

04

列舉類

enumActivityEnum{
FULL30_MINUS5(Full30Minus5ActivityStrategy.class.getName(),"滿30元減5")
,FULL200_DISCOUNT8(Full200Discount8ActivityStrategy.class.getName(),"滿200元,8折優惠")
,UNKNOW_ACTIVITY("未知活動策略","未知活動策略");
privateString value;
privateString description;
ActivityEnum(String value,String description){
this.value=value;
this.description=description;
}
publicString getValue() {
returnvalue;
}
publicString getDescription() {
returndescription;
}
}

05

測試

publicclassActivityStrategyTest{
publicstaticvoidmain(String[] args) {
//輸入金額201.5
BigDecimal beforeDiscount=BigDecimal.valueOf(201.5);
ActivityEnum activityEnum;
if(beforeDiscount.doubleValue()>200){
activityEnum=ActivityEnum.FULL200_DISCOUNT8;
}elseif(beforeDiscount.doubleValue()>30){
activityEnum=ActivityEnum.FULL30_MINUS5;
}else{
activityEnum=ActivityEnum.UNKNOW_ACTIVITY;
}
System.out.printf("該金額對應的策略是:%s%n",activityEnum.getDescription());
//具體業務,不用改動,變化的是引數,當有新的活動策略要新增時,只需要改動列舉引數即可
ActivityStrategy strategy = ActivityStrategyFactory.getInstance().getActivityStrategy(activityEnum.getValue());
BigDecimal afterDiscount = strategy.getDiscount(beforeDiscount);
System.out.println(afterDiscount);
}
}

f97431503584c1856fad5c5b200aaef5.png

7d2a626f282a000d81ded213dc4914dc.gif

寫在最後

總結:本片使用列舉+工廠模式+策略模式去掉多重if...else,對於設計模式本小編也在不斷研究中,雖然看起來很簡單,但想要"悟"懂,也絕非易事,正所謂大道至簡,設計模式也是我們程式設計中的基石,常言道:有道無術,其術可求也,有術無道,止於術!神即道,道即規律,道法自然.當然,此道非彼道,俗語云:"道可道,非常道".

往期精彩文章

  1. 關於BufferReader裝飾設計模式的思考

  2. Java設計模式之《觀察者模式》及應用場景

  3. 從【Spring 原始碼的角度】讀懂Java 23種設計模式之:動態代理設計模式

  4. 一文讀懂Java 23種設計模式之:單例設計模式

如果喜歡,歡迎點贊分享給你身邊需要的人!

我欲尋花問路,直入白雲深處。

0780ea820100aa760bf4a8d2774eecaa.gif

67749a0aea90c2cadd4ea884360da481.gif

d5b30854932539745348acdb6d08a489.png