哲學上說存在即合理。一些初級程序員,包括筆者也曾經在內心說過:“XX這鳥毛東西有什麼用啊,根本就沒必要這麼做,真不知道爲什麼會有這東西”,就拿着這設計模式來說,以前接觸的時候總覺得好複雜,小小的功能要分好幾層,隨着項目經驗的積累,才發現這話說出來真的是打臉啊。是自己的無知導致狂妄的想法。
不是設計模式沒有用,而是你不會!(啊!又被打臉)
最近在寫SDK,架構項目,項目寫到一半,回頭看看,總覺得自己的代碼平平無奇。而且在一些優秀的開源框架中出現的代碼寫法,根本沒有用過。於是嘗試着看看開源代碼,突然發現原來同一種功能有這麼多種實現方式,而且覺得很帥。(所謂的很帥是個人的看法,作爲一個程序員,儘量不要寫出很挫的代碼,類似一個方法裏面有十幾個 if 語句,或者4,5個類中,一半的代碼是重複的,只是小部分代碼是變動的,那麼這時候,就應該停下來好好想想是不是自己代碼寫的有問題了,是不是還有更優秀的實現方式)。其實,代碼繁雜還是一回事,對沒有強迫症的人影響不大,但是,代碼擴展性不好,不易維護,那就是對所有人都是致命的了。簡直會讓人抓狂。
今天記錄一下 策略模式,博文作爲筆記記錄
策略模式:定義了算法族,分別封裝起來,讓它們之間可相互替換,此模式讓算法的變化獨立於使用算法的客戶
什麼意思?別問我,我也不知道。臥槽,那學個毛線,算了,先看看在Android中什麼時候使用到了策略模式
listView.setAdapter(new BAdapter());
沒錯,所有Android程序員都是使用過的方法,對着這行代碼,試着理解一下策略模式的定義:
定義了算法族,分別封裝起來
new BAdapter() 繼承 BaseAdapter 具體算法在 getView 中實現。不同的Adapter繼承 BaseAdapter 實現自己的UI佈局,相當於定義了算法族,分別封裝起來。
讓它們之間可相互替換
new AAdapter(), new BAdapter(),new CAdapter() 對於這些一個個獨立封裝起來的算法,他們之間可以相互替換,被設置到 listView 中。
此模式讓算法的變化獨立於使用算法的客戶
這裏客戶是指這些算法的調用者 listView 。在A,B,CAdapter() 中的算法變化,完全獨立於 listView ,對於新增的算法,不用再使用 if 語句判斷該使用哪一種,客戶直接使用算法就可以,算法的實現也是獨立的。大大提高了程序的擴展性,和維護性。媽媽再也不用擔心我修改一個小功能導致4,5個類的代碼要修改了。
具體實現
在網上查閱資料的時候看到很多人以銷售商品是結算價格舉例,【輸入商品的價格和數量,得出總價,現在商店促銷搞活動,商品打折(7折,8折…),滿減(滿400立減40…)】,這裏拋磚引玉,具體看看代碼,這裏就不貼參考的連接了,如有雷同,純屬巧合。直接看代碼
- 折扣方式接口,面向接口編程,保持了繼承的優點(代碼重用),比繼承更靈活(算法獨立,可以任意擴展)。
package cn.design.java.strategy;
public interface IDiscount {
public double getPrice(double price, int quantity);
}
- 折扣方式—打折,實現IDisCount,設置折扣值 setDiscount(double discount),(7折,8.8折,等等),重寫 getPrice(double price, int quantity) 方法實現折扣算法。
package cn.design.java.strategy;
/**
* 折扣方式-打折
*
* @author Ruffian
* @date 2016年5月11日
*
*/
public class RebateDis implements IDiscount {
// 折扣
private double discount;
public double getDiscount() {
return discount;
}
public void setDiscount(double discount) {
this.discount = discount;
}
@Override
public double getPrice(double price, int quantity) {
double sellPrice = price * quantity;
if (discount > 0) {
sellPrice = sellPrice * discount;
}
return sellPrice;
}
}
- 折扣方式—滿減,實現IDisCount,設置折扣消費條件 setCondition(int conditionMoney, int reduceMoney),(滿400立減40,等),重寫 getPrice(double price, int quantity) 方法實現折扣算法。
package cn.design.java.strategy;
/**
* 折扣方式-滿減
*
* @author Ruffian
* @date 2016年5月11日
*
*/
public class ReduceDis implements IDiscount {
// 滿減條件金額
private int conditionMoney;
// 立減金額
private int reduceMoney;
public void setCondition(int conditionMoney, int reduceMoney) {
this.conditionMoney = conditionMoney;
this.reduceMoney = reduceMoney;
}
@Override
public double getPrice(double price, int quantity) {
double sellPrice = price * quantity;
if (sellPrice > conditionMoney) {
sellPrice = sellPrice - reduceMoney;
}
return sellPrice;
}
}
- 客戶類
基本的算法寫完了,接下來編寫一個客戶類,這裏相當於,編寫 listView 類,以及 setAdapter()
package cn.design.java.strategy;
/**
* 客戶使用類-策略模式
*
* @author Ruffian
* @date 2016年5月11日
*
*/
public class DiscountStrategy {
// 折扣方式
private IDiscount discount;
public void setDiscount(IDiscount discount) {
this.discount = discount;
}
// 計算價格
public void calculatePrice(double price, int quantity) {
double sellPrice = price * quantity;
String discountName = "default";
if (discount != null) {
discountName = discount.getClass().getName();
sellPrice = discount.getPrice(price, quantity);
}
System.out.println("折扣方式: " + discountName + " 折後價格: " + sellPrice);
}
}
- 測試類
package cn.design.java.strategy;
public class Test {
public static void main(String[] args) {
// 折扣方式
IDiscount reduceDis = new ReduceDis();
IDiscount rebateDis = new RebateDis();
DiscountStrategy discountStrategy = new DiscountStrategy();
// 滿減(滿400立減40)
((ReduceDis) reduceDis).setCondition(400, 40);
discountStrategy.setDiscount(reduceDis);
discountStrategy.calculatePrice(138.5, 3);
// 8.8折
((RebateDis) rebateDis).setDiscount(0.88);
discountStrategy.setDiscount(rebateDis);
discountStrategy.calculatePrice(138.5, 3);
// default
discountStrategy.setDiscount(null);
discountStrategy.calculatePrice(138.5, 3);
}
}
- 打印結果
一個流程測試下來了,有沒有發現 策略模式 有什麼奇妙的地方?當然有,多了去了!現在看看測試類,這裏我只需要將我需要打折的方式設置進去,就可以調用對應的折扣算法,每一種折扣方式的算法獨立,就算修改算法實現方式,不會影響到 客戶 的調用方式。這還不算什麼,假如客戶提出新的需求,添加一種新的折扣方式,沒問題,新增一種折扣類,實現算法,調用的時候,直接 new 然後 setDiscount() ,OK,搞定,完全不會影響到之前的代碼,哪怕之前的2種算法是誰寫的,完全不用去理會。
以上是筆者對 策略模式 的一點點理解,記錄下來當做筆記使用,如有不正之處,懇請指正出來,共同進步。