Android 設(shè)計(jì)模式:(七)策略模式

前言
本文是對(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ò)展性。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末吓肋,一起剝皮案震驚了整個(gè)濱河市凳怨,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌是鬼,老刑警劉巖肤舞,帶你破解...
    沈念sama閱讀 218,386評(píng)論 6 506
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異均蜜,居然都是意外死亡李剖,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,142評(píng)論 3 394
  • 文/潘曉璐 我一進(jìn)店門(mén)囤耳,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)篙顺,“玉大人,你說(shuō)我怎么就攤上這事充择〉旅担” “怎么了?”我有些...
    開(kāi)封第一講書(shū)人閱讀 164,704評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵椎麦,是天一觀的道長(zhǎng)宰僧。 經(jīng)常有香客問(wèn)我,道長(zhǎng)观挎,這世上最難降的妖魔是什么琴儿? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 58,702評(píng)論 1 294
  • 正文 為了忘掉前任,我火速辦了婚禮嘁捷,結(jié)果婚禮上造成,老公的妹妹穿的比我還像新娘。我一直安慰自己雄嚣,他們只是感情好晒屎,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,716評(píng)論 6 392
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著缓升,像睡著了一般夷磕。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上仔沿,一...
    開(kāi)封第一講書(shū)人閱讀 51,573評(píng)論 1 305
  • 那天,我揣著相機(jī)與錄音尺棋,去河邊找鬼封锉。 笑死绵跷,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的成福。 我是一名探鬼主播碾局,決...
    沈念sama閱讀 40,314評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼奴艾!你這毒婦竟也來(lái)了净当?” 一聲冷哼從身側(cè)響起,我...
    開(kāi)封第一講書(shū)人閱讀 39,230評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤蕴潦,失蹤者是張志新(化名)和其女友劉穎像啼,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體潭苞,經(jīng)...
    沈念sama閱讀 45,680評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡忽冻,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,873評(píng)論 3 336
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了此疹。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片僧诚。...
    茶點(diǎn)故事閱讀 39,991評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖蝗碎,靈堂內(nèi)的尸體忽然破棺而出湖笨,到底是詐尸還是另有隱情,我是刑警寧澤蹦骑,帶...
    沈念sama閱讀 35,706評(píng)論 5 346
  • 正文 年R本政府宣布慈省,位于F島的核電站,受9級(jí)特大地震影響脊串,放射性物質(zhì)發(fā)生泄漏辫呻。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,329評(píng)論 3 330
  • 文/蒙蒙 一琼锋、第九天 我趴在偏房一處隱蔽的房頂上張望放闺。 院中可真熱鬧,春花似錦缕坎、人聲如沸怖侦。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 31,910評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)匾寝。三九已至,卻和暖如春荷腊,著一層夾襖步出監(jiān)牢的瞬間艳悔,已是汗流浹背。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 33,038評(píng)論 1 270
  • 我被黑心中介騙來(lái)泰國(guó)打工女仰, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留猜年,地道東北人抡锈。 一個(gè)月前我還...
    沈念sama閱讀 48,158評(píng)論 3 370
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像乔外,于是被迫代替她去往敵國(guó)和親床三。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,941評(píng)論 2 355

推薦閱讀更多精彩內(nèi)容