Java與設計模式-策略模式


     在實際開發中,可能會遇到這樣一個情況,某一功能的實現分為多種算法,這些算法可以認定為策略,在實際操作時選擇不同算法或策略進行操作得出最終結果。在實際生活中,這些例子也是舉不勝舉,例如,商場舉行活動,滿100元減10元,滿200元減30元,滿500元減100元等等...這樣每消費一筆,根據這一筆錢消費的多少,計算最終應支付的錢對應着不同的算法,這些對應的不同計算方法就可以認定為是不同的策略。在某東購物時,根據不同的用戶等級,打折力度也是不同的。

    策略模式的UML類圖參照下圖:

  

    假如沒有策略模式,實現某東購物計算最終付款的方法怎樣呢?

   

package com.strategy.demo;

public class NoStrategy {
/**
* 不使用測量模式實現
* @param args
*/
private static final int NOCARDUSER=1;
private static final int IRONCARDUSER=2;
private static final int GOLDCARDUSER=3;


public static void main(String[] args) {
NoStrategy NoStrategy1=new NoStrategy();
NoStrategy NoStrategy2=new NoStrategy();
NoStrategy NoStrategy3=new NoStrategy();

System.out.println("沒有卡牌的買家買100元貨物最終應付款:"+NoStrategy1.getPrice(100.0, 1));

System.out.println("鐵牌的買家買100元貨物最終應付款:"+NoStrategy2.getPrice(100.0, 2));

System.out.println("金牌的買家買100元貨物最終應付款:"+NoStrategy3.getPrice(100.0, 3));

}


private double getNoCardPrice(double price){
return price;
}

private double getIronCardPrice(double price){
return price*0.9;
}

private double getGoldCardPrice(double price){
return price*0.7;
}


private double getPrice(double price,int type){
if(type==NOCARDUSER){
return getNoCardPrice(price);
}else if(type ==IRONCARDUSER){
return getIronCardPrice(price);
}else if(type ==GOLDCARDUSER){
return getGoldCardPrice(price);
}else {
return 0;
}
}

}


運行實例:

呀,得出正確的答案了,這時你是不是應該滿足了呢,應該高枕無憂了呢?突然,主管說要增加鑽石用戶的類別,鑽石用戶打六折,這時你怎么實現呢?在里面在增加鑽石用戶的類型,再增加計算鑽石用戶的方法,再再最后的判斷里增加i f else?  這樣的確可以實現功能,但是是不是不滿足開閉原則呢?而且隨着用戶種類的不斷增加,你的if  else是不是也越來越長,邏輯也越來越復雜呢?導致系統擴展性和穩定性越來越差呢? 所以,這種方式在實際中顯然實不可取的,下面我們看一下如何使用策略模式來實現上面的需求。

1.PriceStrategyInterface 接口,對應UML類圖中的Strategy接口:

package com.strategy.demo;public interface PriceStrategyInterface {double calPrice(double price);}


2.實現類,無卡用戶:

package com.strategy.demo;public class NoCardUserStrategy implements PriceStrategyInterface {/** * 無牌買家,原價 */@Overridepublic double calPrice(double price) {return price;}}


3.實現類,鐵卡用戶:

package com.strategy.demo;public class IronCardUserStrategy implements PriceStrategyInterface {/* * 鐵牌買家 * (non-Javadoc) * @see com.strategy.demo.PriceStrategyInterface#calPrice(double) */@Overridepublic double calPrice(double price) {return price*0.9;}}


4.實現類,金卡用戶:

package com.strategy.demo;public class GoldCardUserStrategy implements PriceStrategyInterface {/** * 金牌買家 */@Overridepublic double calPrice(double price) {return price*0.7;}}


5.環境對象,用來操作策略:

package com.strategy.demo;public class PriceContext {/** * 操作類 */PriceStrategyInterface priceStrategyInterface;/* * 通過初始化傳入對象 */public PriceContext(PriceStrategyInterface priceStrategyInterface) {this.priceStrategyInterface=priceStrategyInterface;}/* * 通過對象計算返回值 */public double getPrice(double price){ return priceStrategyInterface.calPrice(price);}}

環境對象初始化時,將對應的策略對象傳入,然后調用方法返回計算值。

6.構建測試類,測試:

package com.strategy.demo;public class TestClass {public static void main(String[] args) {PriceContext priceContext=new PriceContext(new NoCardUserStrategy());System.out.println("沒有卡牌的買家買100元貨物最終應付款:"+priceContext.getPrice(100.0));PriceContext priceContext2=new PriceContext(new IronCardUserStrategy());System.out.println("鐵牌的買家買100元貨物最終應付款:"+priceContext2.getPrice(100.0));PriceContext priceContext3=new PriceContext(new GoldCardUserStrategy());System.out.println("金牌的買家買100元貨物最終應付款:"+priceContext3.getPrice(100.0));}}

運行上面的實例:

得到了和第一個方法一樣的正確答案,這時我們假如要增加一個鑽石買家的種類,怎么實現呢?我們只需要增加一個策略實現類:

package com.strategy.demo;public class DiamondUserStrategy implements PriceStrategyInterface {@Overridepublic double calPrice(double price) {return price*0.6;}}


然后測試類增加一條鑽石類買家的購物:

package com.strategy.demo;public class TestClass {public static void main(String[] args) {PriceContext priceContext=new PriceContext(new NoCardUserStrategy());System.out.println("沒有卡牌的買家買100元貨物最終應付款:"+priceContext.getPrice(100.0));PriceContext priceContext2=new PriceContext(new IronCardUserStrategy());System.out.println("鐵牌的買家買100元貨物最終應付款:"+priceContext2.getPrice(100.0));PriceContext priceContext3=new PriceContext(new GoldCardUserStrategy());System.out.println("金牌的買家買100元貨物最終應付款:"+priceContext3.getPrice(100.0));PriceContext priceContext4=new PriceContext(new DiamondUserStrategy());System.out.println("鑽石卡的買家買100元貨物最終應付款:"+priceContext4.getPrice(100.0));}}


運行實例:



是不是擴展起來特別容易?條理也十分清晰。總結一下策略模式的優點:

1. 結構清晰,使用簡單直觀;

2. 系統耦合性降低,擴展方便;

3. 操作封裝徹底,數據更為安全。(在TestClass中,只知道相關實現類,並不涉及具體計算方法)

當然,策略方式也存在一定的缺點:

由圖可以直觀的看出,隨着策略的不斷增加,子類數量變得龐大。

 

喜歡的朋友關注我和我的微信平台

 

   


注意!

本站转载的文章为个人学习借鉴使用,本站对版权不负任何法律责任。如果侵犯了您的隐私权益,请联系我们删除。



 
粤ICP备14056181号  © 2014-2021 ITdaan.com