二、政策模式-商場促銷活動
以商場收銀為例,了解并實踐“政策模式”。
- 簡單商場促銷活動描述:營業員提供商品單價、數量、商場目前的活動(滿減、打折等),計算使用者最終需要支付的金額。
一、面向過程的實作方式
1 package secondStrategy;
2 import java.text.DecimalFormat;
3 public class StrategyTest {
4 public static void main(String[] args) {
5 // 營業員提供資訊
6 double total=0;
7 double price=2;
8 int num=3;
9 String promotions="打8折";//或者“滿100-30”
10
11 // 計算待付金額
12 double totalPrice=price*num;
13 total=total+totalPrice;
14
15 switch (promotions) {
16 case "打8折":total=total*0.8;break;
17 case "滿100-30": total=total-(total/100)*30; // "/"取整。“%”取餘
18 default:
19 break;
20 }
21 DecimalFormat df = new DecimalFormat("#.##"); // 如果寫成0.00,結果就一定是兩個小數
22 System.out.println("單價:"+price+";數量:"+num+";原價:"+totalPrice+";活動:"+promotions+";活動價:"+df.format(total));
23
24 }
25 }
缺點:當有新的活動時,就要不停地複制程式代碼,新增一個類别,這使程式的重複性增加,可維護性變差。
二、通過簡單工廠實作
1、UML圖結構

2、語言描述
- 父類:現金收費抽象類CashSuper
- 抽象方法:acceptCash( 原價){ return 活動價}
- 子類:正常收費CashNormal、
- 實作父類抽象方法:acceptCash( 原價){ return 原價}
- 子類:打折類CashRebate
- 私有屬性:moneyRebate;
- 構造方法:帶moneyRebate的
- 實作父類抽象方法:acceptCash( 原價){ return 原價*moneyRebate}
- 子類:滿減類CashRerurn
- 私有屬性:moneyCondition; moneyReturn;
- 構造方法:帶上面倆參數的
- 實作父類抽象方法:acceptCash( 原價){ return 原價-滿減價}
- 工廠:CashFactory
- createCashAccept( String type)
- 用戶端:price/ num / "活動type"
- 執行個體化
- 輸出
三、通過政策模式來設計
1、UML圖結構
2、文字描述
- 父類政策類:CashSuper
- 抽象方法:acceptCash( 原價){ return 活動價}
- 具體政策子類1:正常收費CashNormal、
- 實作父類抽象方法:acceptCash( 原價){ return 原價}
- 具體政策子類2:打折類CashRebate
- 私有屬性:moneyRebate;
- 構造方法:帶moneyRebate的
- 實作父類抽象方法:acceptCash( 原價){ return 原價*moneyRebate}
- 具體政策子類3:滿減類CashRerurn
- 私有屬性:moneyCondition; moneyReturn;
- 構造方法:帶上面倆參數的
- 實作父類抽象方法:acceptCash( 原價){ return 原價-滿減價}
- Context類:CashContext
- 私有屬性:CashSuper cs;
- 構造方法:CashContext( CashSuper csuper){ this....}
- 取得金額方法: getResult(){ cs.acceptCash()}
- 用戶端:price/ num / "活動type"
- switch(type) : cc=new CashContext( new CashRebate( canshu1, canshu2))
- cc.getResult()
四、政策模式與工廠模式相結合
1、UML圖結構
2、文字描述
- 父類政策類:CashSuper
- 抽象方法:acceptCash( 原價){ return 活動價}
- 具體政策子類1:正常收費CashNormal、
- 實作父類抽象方法:acceptCash( 原價){ return 原價}
- 具體政策子類2:打折類CashRebate
- 私有屬性:moneyRebate;
- 構造方法:帶moneyRebate的
- 實作父類抽象方法:acceptCash( 原價){ return 原價*moneyRebate}
- 具體政策子類3:滿減類CashRerurn
- 私有屬性:moneyCondition; moneyReturn;
- 構造方法:帶上面倆參數的
- 實作父類抽象方法:acceptCash( 原價){ return 原價-滿減價}
- Context類:CashContext
- 私有屬性:CashSuper cs;
- 構造方法:CashContext( String type){ switch()}
- 取得金額方法: getResult(){ cs.acceptCash()}
- 用戶端:price/ num / "活動type"
- new CashContext( type )
3、java代碼實作
- 父類政策類:CashSuper
1 package secondStrategy;
2
3 public abstract class CashSuper {
4 public abstract double acceptCash(double money);
5 }
-
- 具體政策子類1:正常收費CashNormal
1 package secondStrategy;
2
3 public class CashNormal extends CashSuper {
4
5 @Override
6 public double acceptCash(double money) {
7 return money;
8 }
9
10 }
-
- 具體政策子類2:打折類CashRebate
1 package secondStrategy;
2
3 // 打折類
4 public class CashRebate extends CashSuper {
5 private double moneyRebate=0;
6 // 構造方法,初始化時應傳入折扣
7 public CashRebate(double moneyRe) {
8 this.moneyRebate=moneyRe;
9 }
10 @Override
11 public double acceptCash(double money) {
12 double result=0;
13 result=money*moneyRebate;
14 return result;
15 }
16
17 }
-
- 具體政策子類3:滿減類CashRerurn
1 package secondStrategy;
2
3 public class CashReturn extends CashSuper {
4 private double moneyCondition=0; //滿減門檻
5 private double moneyReturn=0; // 滿減金額
6
7 public CashReturn(double moneyCon,double moneyRe) {
8 // TODO Auto-generated constructor stub
9 this.moneyCondition=moneyCon;
10 this.moneyReturn=moneyRe;
11 }
12
13 @Override
14 public double acceptCash(double money) {
15 double result=0;
16 result=money-(money/moneyCondition)*moneyReturn;
17 return result;
18 }
19
20 }
- Context類:CashContext
1 package secondStrategy;
2
3 public class CashContext {
4 private CashSuper cSuper;
5 public CashContext( String type) {
6 switch (type) {
7 case "打8折": this.cSuper=new CashRebate(0.8); break;
8 case "滿100-30": this.cSuper=new CashReturn(100,30);break;
9 default:this.cSuper=new CashNormal();
10 break;
11 }
12 }
13 public double getResult(double money){
14 return this.cSuper.acceptCash(money);
15 }
16 }
- 用戶端:
package secondStrategy;
import java.text.DecimalFormat;
public class StrategyTest {
public static void main(String[] args) {
// 營業員提供資訊
double total=0;
double price=2;
int num=3;
String promotions="打8折";//或者“滿100-30”
// 計算待付金額
double totalPrice=price*num;
total=total+totalPrice;
switch (promotions) {
case "打8折":total=total*0.8;break;
case "滿100-30": total=total-(total/100)*30; // "/"取整。“%”取餘
default:
break;
}
DecimalFormat df = new DecimalFormat("#.##"); // 如果寫成0.00,結果就一定是兩個小數
System.out.println("單價:"+price+";數量:"+num+";原價:"+totalPrice+";活動:"+promotions+";活動價:"+df.format(total));
}
}
運作結果:
五、總結說明
1、定義:政策模式是一種定義一系列算法的方法,從概念上看,所有這些算法完成的都是相同的工作,隻是實作不同。它可以有相同的方式調用所有的算法,減少了各種算法類與使用算法類之間的耦合。
2、政策模式的Strategy類層次為Context定義了一系列可供重用的算法或行為。繼承有助于析取出這些算法的公共功能——計費結果getResult()。
3、優點:
- 它可以有相同的方式調用所有的算法,減少了各種算法類與使用算法類之間的耦合。
- 簡化了單元測試,因為每個算法都有自己的類,可以通過自己的接口單獨測試。
4、特點:
- 政策模式就是用來封裝算法的,但在實踐中,發現可以用它來封裝幾乎任何類型的規則,隻要在分析過程中聽到需要在不同時間應用不同的業務規則,就可以考慮使用政策模式處理這種變化的可能性。
- 在基本的政策模式中,選擇所用具體實作的職責有用戶端對象承擔,并轉給政策模式的Context對象。本身雖然沒有接觸用戶端需要選擇判斷的壓力,但将簡單工廠與政策模式結合之後,由Context來承擔選擇的工作,最大化地減輕了用戶端的職責。
- 任何需求都是需要成本的,日後會講到反射機制,可以不用選擇,以後再說咯!
發表于
2018-11-20 17:57
左蘭蘭
閱讀(697)
評論(0)
編輯
收藏
舉報