前言
本文是對(duì)《Adroid 源碼設(shè)計(jì)模式解析與實(shí)戰(zhàn)》 何紅輝资溃、關(guān)愛(ài)民 著 人民郵電出版社所做的讀書(shū)筆記大莫。文章是對(duì)本書(shū)的一些列學(xué)習(xí)筆記,如若有侵犯到作者權(quán)益拓瞪,還望作者能聯(lián)系我缴罗,我會(huì)及時(shí)下架。
這本書(shū)不錯(cuò)祭埂,有興趣的同學(xué)可以買(mǎi)原書(shū)看看面氓。
感興趣的朋友歡迎加入學(xué)習(xí)小組QQ群: 193765960。
版權(quán)歸作者所有蛆橡,如有轉(zhuǎn)發(fā)舌界,請(qǐng)注明文章出處:https://xiaodanchen.github.io/archives/
相關(guān)文章:
Android 設(shè)計(jì)模式:(一)面向?qū)ο蟮牧笤瓌t
Android 設(shè)計(jì)模式:(二)單例模式
Android 設(shè)計(jì)模式:(三)Builder模式
Android 設(shè)計(jì)模式:(四)原型模式
Android 設(shè)計(jì)模式:(五)工廠方法模式
Android 設(shè)計(jì)模式:(六)抽象工廠模式
Android 設(shè)計(jì)模式:(七)策略模式
1. 策略模式的定義
假如在開(kāi)發(fā)中遇到下列情況:
- 針對(duì)同一問(wèn)題有多重處理方式,他們僅僅是具體行為有差別泰演。
- 需要安全的封裝多種同一類(lèi)型的操作呻拌。
- 同一個(gè)抽象類(lèi)有多個(gè)子類(lèi),而子類(lèi)的使用又是互斥的睦焕。
遇到上述幾種情況時(shí)藐握,我們可以使用策略模式。策略模式定義了一系列的算法复亏,并將每一個(gè)算法封裝起來(lái)趾娃,而且使他們還可以相互替換。策略模式讓算法獨(dú)立于使用它的客戶而獨(dú)立變化缔御。
2. 策略模式的實(shí)現(xiàn)
通常如果一個(gè)問(wèn)題有多個(gè)解決方案時(shí),最簡(jiǎn)單的方法就是利用if-else或者switch語(yǔ)句方式根據(jù)不同的情景選擇不同的解決方案妇蛀,但這種簡(jiǎn)單的方案問(wèn)題太多耕突,例如耦合性太高、代碼臃腫评架、難于維護(hù)等眷茁。而且違反開(kāi)閉原則,而應(yīng)對(duì)這種情況策略模式是很好的選擇纵诞。
舉個(gè)栗子:假如我們要設(shè)計(jì)一個(gè)出行交通工具(公交車(chē)上祈、地鐵)計(jì)費(fèi)模塊。
2.1 屌絲程序猿小明
源碼
/**
* 價(jià)格計(jì)算器類(lèi)
*/
public class PriceCalculator{
private static final int BUS = 1;//公交車(chē)類(lèi)型
private static final int SUBWAY = 2;//地鐵類(lèi)型
public static void main(String[] args){
PriceCalculator calculator = new PriceCalculator();
System.out.println("坐16公里的公交車(chē)票價(jià)為:"+calculator.calculatePrice(16,BUS));
System.out.println("坐16公里的地鐵票價(jià)為:"+calculator.calculatePrice(16,SUBWAY));
}
/**
* 公交車(chē),十公里之內(nèi)1元登刺,超過(guò)十公里后沒(méi)加一元錢(qián)可以乘車(chē)公里籽腕。
*/
private int busPrice(int km){
//超過(guò)10公里的中國(guó)
int extraTotal = km-10;
//超過(guò)的距離是5公里的倍數(shù)
int extraFactor = extraTotal/5;
//超過(guò)的距離對(duì)5公里取余
int fraction = extraTotal%5;
//計(jì)算價(jià)格
int price = 1+extraFactor*1;
return fraction>0?++price:price;
}
/**
* 地鐵纸俭,6公里(含)之內(nèi)3元皇耗,6~12公里(含)4元,
* 12~22公里(含)5元揍很,22~32公里(含)6元郎楼,。
*/
private int subwayPrice(int km){
if(km<=6){
return 3;
}else if(km>6 && km<=12){
return 4;
}else if(km>12 && km<=22){
return 5;
}else if(km>22 && km<=32){
return 6;
}
return 7;
}
int calculatePrice(int km,int type){
if(type == BUS){
return busPrice(km);
}else if(type == SUBWAY){
return subwayPrice(km);
}
return 0;
}
}
解析
首先窒悔,PriceCalculator類(lèi)很明顯的問(wèn)題就是違反了單一職責(zé)原則呜袁,他承擔(dān)了計(jì)算公交車(chē)和地鐵乘車(chē)價(jià)格的職責(zé)。
其次简珠,PriceCalculator類(lèi)違反了開(kāi)閉原則阶界,通過(guò)if-else語(yǔ)句的形式來(lái)判斷使用哪種計(jì)算方式,當(dāng)我們?cè)黾右环N出行方式時(shí)比如出租車(chē)北救,我們就需要在PriceCalculator類(lèi)中增加一個(gè)方法來(lái)計(jì)算出租車(chē)出行的價(jià)格荐操,并且需要在calculatePrice方法中增加新的條件分支。
這樣隨著業(yè)務(wù)的復(fù)雜珍策,這個(gè)代碼會(huì)越來(lái)越臃腫托启,難以維護(hù)。
2.2 裝逼程序猿小民
小民采用策略模式來(lái)設(shè)計(jì)該功能
源碼
/**
* 計(jì)價(jià)策略接口
*/
public interface CalculateStrategy{
/**
* 按距離計(jì)算價(jià)格
* @param km 距離
* @return 價(jià)格
*/
int calculatePrice(int km);
}
/**
* 公交車(chē)計(jì)價(jià)策略
*/
public class BusStrategy implements CalculateStrategy{
/**
* 公交車(chē)攘宙,十公里之內(nèi)1元屯耸,超過(guò)十公里后沒(méi)加一元錢(qián)可以乘車(chē)公里。
*/
@Override
public int calculatePrice(int km){
//超過(guò)10公里的中國(guó)
int extraTotal = km-10;
//超過(guò)的距離是5公里的倍數(shù)
int extraFactor = extraTotal/5蹭劈;
//超過(guò)的距離對(duì)5公里取余
int fraction = extraTotal%5;
//計(jì)算價(jià)格
int price = 1+extraFactor*1;
return fraction>0?++price:price;
}
}
/**
* 地鐵計(jì)價(jià)策略
*/
public class BusStrategy implements CalculateStrategy{
/**
* 地鐵疗绣,6公里(含)之內(nèi)3元,6~12公里(含)4元铺韧,
* 12~22公里(含)5元多矮,22~32公里(含)6元,哈打。
*/
@Override
public int calculatePrice(int km){
if(km<=6){
return 3;
}else if(km>6 && km<=12){
return 4;
}else if(km>12 && km<=22){
return 5;
}else if(km>22 && km<=32){
return 6;
}
return 7;
}
}
/**
* 價(jià)格計(jì)算器類(lèi)
*/
public class PriceCalculator{
CalculateStrategy mStrategy;
public static void main(String[] args){
PriceCalculator calculator = new PriceCalculator();
//設(shè)置計(jì)價(jià)策略
calculator.setStrategy(new BusStrategy());
System.out.println("坐16公里的公交車(chē)票價(jià)為:"+calculatePrice(16));
}
public void setStrategy(CalculateStrategy strategy;){
mStrategy = strategy
}
public int calculatePrice(int km){
if(null == mStrategy){
return 0;
}
return mStrategy.calculatePrice(km);
}
}
解析
經(jīng)過(guò)上面的重構(gòu)之后塔逃,去掉了各種各樣的if-else語(yǔ)句,結(jié)構(gòu)變得更加清晰料仗。
不同的策略封裝符合單一職責(zé)原則湾盗。
PriceCalculator的實(shí)際調(diào)用符合開(kāi)閉原則和依賴注入原則,便于擴(kuò)展立轧。
3. 總結(jié)
策略模式主要用來(lái)分離算法格粪,在相同的行為抽象下有不同的具體實(shí)現(xiàn)策略躏吊。這個(gè)模式很好的演示了開(kāi)閉原則,也就是定義抽象帐萎,注入不同的實(shí)現(xiàn)比伏,從而達(dá)到很好的可擴(kuò)展性。