還為那些設(shè)計模式煩惱嗎—策略模式

策略模式

</br>

前言

很多人在閱讀第三方框架(例如Retrofit)的時候,不太懂或者比較吃力,是因為我們?nèi)鄙僖恍懘a的思維,看代碼的設(shè)計的模式,今天,小菜我說下對策略模式的理解
</br>


介紹

  • 專業(yè)說法:定義了一系列的算法,并將每個算法封裝起來,而且使它們還可以相互替換,策略模式讓算法獨立于使用它的客戶而獨立變化
  • 例子說法:假設(shè),今天,我要為舍友煮一道菜,小菜我買了一塊豬肉,但是,舍友開心的時候,是喜歡吃紅燒肉,則我要做紅燒肉;難過的時候,是喜歡吃燜豬肉,則我要做燜豬肉:
    1.難過(策略)->做紅燒肉(算法)
    2.開心(策略)->做燜豬肉(算法)
    </br>

改善前的代碼

/**
 * Created by Jenchar on 2016/7/30.
 */
public class Meat {
    public static final String HAPPY="開心";
    public static final String SAD="難過";
    public static final String REDMEAT="紅燒肉";
    public static final String BRAISEMEAT="燜豬肉";

    public static void main(String[] args) {
        Meat meat=new Meat();
        meat.chooseFood(SAD,BRAISEMEAT);
    }
    private void chooseFood(String fellings,String type) {
        if(fellings.equals(HAPPY)){
            codeRedMeat(type);
        }else{
            cookBraiseMeat(type);
        }
    }

    private void cookBraiseMeat(String meat) {
        System.out.println("他"+HAPPY+"的時候,"+"我要為他煮"+meat);
    }

    private void codeRedMeat(String meat) {
        System.out.println("他"+SAD+"的時候,"+"我要為他煮"+meat);
    }
}

輸出結(jié)果:
他難過的時候,我要為他煮紅燒肉
分析:

Meat類很明顯的問題是并不是單一職責(zé)(簡單來說,就是一個類只有一種功能),首先它承擔(dān)了做紅燒肉和做燜豬肉的職責(zé),另一個問題就是通過if-else的形式來判斷做哪一種。小菜想,當(dāng)我舍友他發(fā)神經(jīng)病,興奮的時候,會喜歡吃炸豬肉呢,那么我就需要在Meat類中增加一個方法去做炸豬肉,并且要在 chooseFood(String fellings,String type)方法里又增加一個判斷,代碼如下:
</br>

/**
 * Created by Jenchar on 2016/7/30.
 */
public class Meat {
    public static final String HAPPY="開心";
    public static final String SAD="難過";
    public static final String REDMEAT="紅燒肉";
    public static final String BRAISEMEAT="燜豬肉";
    /**
     * 增加的
     */
    public static final String  EXCITED="興奮";
    public static final String  FLYINGMEAT="炸豬肉";

    public static void main(String[] args) {
        Meat meat=new Meat();
        meat.chooseFood(EXCITED,FLYINGMEAT);

    }
    private void chooseFood(String fellings,String type) {
        if(fellings.equals(HAPPY)){
            codeRedMeat(type);
        }else if(fellings.equals(SAD)){
            cookBraiseMeat(type);
            /**
             * 增加的
             */
        }else if(fellings.equals(EXCITED)){
            cookFlyingMeat(type);
        }
    }

    /**
     *增加的
     */
    private void cookFlyingMeat(String type) {
        System.out.println("他"+EXCITED+"的時候,"+"我要為他煮"+type);
    }

    private void cookBraiseMeat(String meat) {
        System.out.println("他"+HAPPY+"的時候,"+"我要為他煮"+meat);
    }

    private void codeRedMeat(String meat) {
        System.out.println("他"+SAD+"的時候,"+"我要為他煮"+meat);
    }
}
輸出結(jié)果:
他興奮的時候,我要為他煮炸豬肉

再分析:

看看 chooseFood(String fellings,String type)這個方法,現(xiàn)在代碼是不是很亂了,各種if-else語句纏繞在其中?當(dāng)小菜的舍友,因為精神分裂,又想吃另外一種,那么,我又要在chooseFood增加if-else。當(dāng)if-else語句多了,就會很容易看錯,寫錯,而且,代碼臃腫,小的項目,小的類雖然過得去,但是到了大的項目,必然會很亂,難以維護(hù)。所以,因這種情況 ,小菜我開始引進(jìn)了一種設(shè)計模式,“策略模式”
</br>


改善后的代碼

首先小菜我需要定義一個抽象的做肉接口,命名CookStrategy,代碼如下:

/**
 * 做肉的接品
 */
public interface CookStrategy {
    /**
     * 根據(jù)舍友的情感來做肉
     * @param feelings
     */
    void cook(String feelings);
}

接著對于做紅燒肉還是燜豬肉,小菜我覺得應(yīng)該都有一個獨立的做肉策略類,這些類都實現(xiàn)上面說的CookStrategy接口,代碼如下:
CookRedMeat.java:

/**
 * 做紅燒肉的類
 */
public class CookRedMeat implements CookStrategy{
    public static final String REDMEAT="紅燒肉";
    /**
     * 開始做他喜歡的紅燒肉
     * @param feelings
     */
    @Override
    public void cook(String feelings) {
        System.out.println("他"+feelings+"的時候,"+"我要為他煮"+REDMEAT);
    }
}

CookBraiseMeat.java:

/**
 * 做燜肉的類
 */
public class CookBraiseMeat implements CookStrategy {
    public static final String BRAISEMEAT="燜豬肉";
    @Override
     /**
     * 開始做他喜歡的燜豬肉
     * @param feelings
     */
    public void cook(String feelings) {
          System.out.println("他"+feelings+"的時候,"+"我要為他煮"+BRAISEMEAT);
    }
}

最后,我們再創(chuàng)建一個的Meat類。

public class Meat {
    public static final String HAPPY="開心";
    public static final String SAD="難過";
    /**
     * 持有CookStrategy對象
     */
    private CookStrategy mCookStrategy;
    public static void main(String[] args) {
        Meat meat=new Meat();
        meat.setCookStrategy(new CookBraiseMeat());
        meat.cookFood(SAD);
    }

    /**
     * 把子類的引用賦值到mCookStrategy,就可以調(diào)用子類的方法。
     * @param cookStrategy
     */
    private void setCookStrategy(CookStrategy cookStrategy) {
        mCookStrategy=cookStrategy;
    }
    private void cookFood(String feelings){
        mCookStrategy.cook(feelings);
    }

}
最后分析

通過改善前后的代碼,可以看出:

  • 前者:通過if-else解決問題,代碼臃腫,邏輯復(fù)雜,難以升級與維護(hù),沒有結(jié)構(gòu)可言
  • 后者:通過建立接口,將不同的策略構(gòu)建成一個具體的策略實現(xiàn) ,通過不同的策略實現(xiàn)算法替換,從而更好地增加擴(kuò)展性,直觀性。
    </br>

結(jié)論與使用場景

  • 針對同一類型的問題,多種處理,僅僅是具體為行有差別(做紅燒肉,做燜豬肉)
  • 出現(xiàn)同一抽象類有多個子類,雖然使用if-else或者switch-case來選擇子類的(根據(jù)舍友的心情來做肉)
  • 需要安全地封裝多種同一類型的操作時(做紅燒肉,做燜豬肉這些操作時)
    </br>

喜歡我的朋友,可以與我一起討論問題,我也是學(xué)習(xí)者,希望與大學(xué)一起學(xué)習(xí)。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 228,739評論 6 534
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 98,634評論 3 419
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 176,653評論 0 377
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經(jīng)常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 63,063評論 1 314
  • 正文 為了忘掉前任,我火速辦了婚禮,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當(dāng)我...
    茶點故事閱讀 71,835評論 6 410
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 55,235評論 1 324
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,315評論 3 442
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 42,459評論 0 289
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 49,000評論 1 335
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 40,819評論 3 355
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 43,004評論 1 370
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,560評論 5 362
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 44,257評論 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,676評論 0 26
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 35,937評論 1 288
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 51,717評論 3 393
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 48,003評論 2 374

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

  • 1 場景問題# 1.1 報價管理## 向客戶報價,對于銷售部門的人來講,這是一個非常重大、非常復(fù)雜的問題,對不同的...
    七寸知架構(gòu)閱讀 5,118評論 9 62
  • 1 場景問題 1.1 報價管理 向客戶報價,對于銷售部門的人來講,這是一個非常重大、非常復(fù)雜的問題,對不同的客戶要...
    4e70992f13e7閱讀 3,102評論 2 16
  • ¥開啟¥ 【iAPP實現(xiàn)進(jìn)入界面執(zhí)行逐一顯】 〖2017-08-25 15:22:14〗 《//首先開一個線程,因...
    小菜c閱讀 6,483評論 0 17
  • 工廠模式類似于現(xiàn)實生活中的工廠可以產(chǎn)生大量相似的商品,去做同樣的事情,實現(xiàn)同樣的效果;這時候需要使用工廠模式。簡單...
    舟漁行舟閱讀 7,798評論 2 17
  • 目錄 本文的結(jié)構(gòu)如下: 引言 什么是策略模式 模式的結(jié)構(gòu) 典型代碼 代碼示例 策略模式和模板方法模式的區(qū)別 優(yōu)點和...
    w1992wishes閱讀 873評論 1 7