設(shè)計模式-策略模式

介紹

在項目開發(fā)中,經(jīng)常會碰到需要根據(jù)不同的條件采用不同的算法止潮,但是這些不同的算法又有些類似。例如商城下單中的打折功能(打八折钞楼、五折、一折)袄琳,滿減功能等等询件。
地圖中根據(jù)采用不同的出行方式計算時間燃乍、金額等等,如下圖宛琅,不同的出行方式使用不同的算法計算需要花費的時間和最短的行駛距離刻蟹。


這里寫圖片描述

結(jié)構(gòu)圖

那這些不同的行為,我們可以把它們封裝成不同的算法嘿辟,根據(jù)用戶選擇的不同采用不同的算法舆瘪,這種可以采用策略模式來實現(xiàn)他們。


這里寫圖片描述

案例

這次的案例就采用壓縮文件的案例红伦,用戶選擇不同的壓縮策略后臺相應采用不同的壓縮算法進行壓縮英古。
**算法接口類Algorithm **

public interface Algorithm {
    void compress();
}

**算法接口類實現(xiàn)類RarAlgorithm **

public class RarAlgorithm implements Algorithm {

    @Override
    public void compress() {
        System.out.println("Rar壓縮文件。昙读。召调。");
    }

}

**算法接口類實現(xiàn)類ZipAlgorithm **

public class ZipAlgorithm implements Algorithm {

    @Override
    public void compress() {
        System.out.println("Zip壓縮文件。蛮浑。唠叛。");
    }

}

算法上下文類AlgorithmContext

public class AlgorithmContext {
    private Algorithm algorithm;

    public AlgorithmContext(Algorithm algorithm) {
        this.algorithm = algorithm;
    }
    
    public void handle(){
        algorithm.compress();
    }
}

業(yè)務類

public class Client {
    public static void main(String[] args) {
        
        //String type = "RarAlgorithm";
        String type = "ZipAlgorithm";
        
        
        AlgorithmContext algorithmContext = null;
        switch (type) {
        case "ZipAlgorithm":
            algorithmContext = new AlgorithmContext(new ZipAlgorithm());
            break;
        case "RarAlgorithm":
            algorithmContext = new AlgorithmContext(new RarAlgorithm());
            break;
        default:
            break;
        }
        
        if (algorithmContext != null) {
            algorithmContext.handle();
        }
        
    }
}

上面就是策略模式的代碼,其實還是有優(yōu)化的地方沮稚,例如下面這一段代碼可以交給算法上下文類AlgorithmContext來決定艺沼,讓業(yè)務類只接觸AlgorithmContext,而不用接觸到具體的算法類蕴掏,真正的實現(xiàn)解耦澳厢。而下面的代碼可以挪到AlgorithmContext中使用簡單工廠模式實現(xiàn)。

switch (type) {
        case "ZipAlgorithm":
            algorithmContext = new AlgorithmContext(new ZipAlgorithm());
            break;
        case "RarAlgorithm":
            algorithmContext = new AlgorithmContext(new RarAlgorithm());
            break;
        default:
            break;
        }

簡單工廠模式和策略模式結(jié)合

修改后的AlgorithmContext類

public class AlgorithmContext {
    private Algorithm algorithm;
    //使用簡單工廠模式
    public AlgorithmContext(String type) {
        switch (type) {
        case "ZipAlgorithm":
            algorithm = new ZipAlgorithm();
            break;
        case "RarAlgorithm":
            algorithm = new RarAlgorithm();
            break;
        default:
            algorithm = new ZipAlgorithm();
            break;
        }
    }
    
    public void handle(){
        algorithm.compress();
    }
}

業(yè)務類

public class Client {
    public static void main(String[] args) {
        
        //String type = "RarAlgorithm";
        String type = "ZipAlgorithm";
        
        //使用簡單工廠模式
        AlgorithmContext algorithmContext = new AlgorithmContext(type);
        
        algorithmContext.handle();
        
    }
}

正常來說這篇博文到這里結(jié)束了囚似,但是仔細想想剩拢,如果增加了一個壓縮算法,那么switch重是不是還要增加一個條件饶唤?那么有沒有辦法解決徐伐?答案是有的,java可以使用反射技術(shù).

使用反射來替換條件判斷

修改后的AlgorithmContext類

public class AlgorithmContext {
    private Algorithm algorithm;
    
    //使用簡單工廠模式
    public AlgorithmContext(String type) {
        try {
            //簡單實現(xiàn)(可用配置文件來配置type對應的類全稱)
            Class clazz = Class.forName("com.dp.strategy.algorithm.impl."+type);
            algorithm = (Algorithm) clazz.newInstance();
        } catch (Exception e) {
            algorithm = new ZipAlgorithm();
            e.printStackTrace();
        }
    }
    
    public void handle(){
        algorithm.compress();
    }
}

上面只是提供個反射思路來替換條件判斷而已募狂,正常項目開發(fā)不會用這種方式办素,更多的會采用配置文件的方式來獲取對應的類,就像spring的配置bean一樣祸穷,就是下面這種方式性穿,有興趣可以研究研究

<bean id="..." class="..." destroy-method="...">
       <!-- collaborators and configuration for this bean go here -->
</bean>

總結(jié)

總的來說,策略模式就是將算法從業(yè)務邏輯中抽取出來雷滚,然后將選擇權(quán)交給用戶需曾,這樣在一定程度上提高了系統(tǒng)的靈活性。策略模式主要優(yōu)點在于對“開閉原則”的完美支持,在不修改原有系統(tǒng)的基礎(chǔ)上可以更換算法或者增加新的算法呆万,它很好地管理算法族商源,提高了代碼的復用性,是一種替換繼承谋减,避免多重條件轉(zhuǎn)移語句的實現(xiàn)方式牡彻;其缺點在于客戶端必須知道所有的策略類,并理解其區(qū)別出爹,同時在一定程度上增加了系統(tǒng)中類的個數(shù)庄吼,可能會存在很多策略類。
那么什么時候可以使用策略模式呢严就?
在一個系統(tǒng)里面有許多類总寻,它們之間的區(qū)別僅在于它們的行為,使用策略模式可以動態(tài)地讓一個對象在許多行為中選擇一種行為盈蛮;一個系統(tǒng)需要動態(tài)地在幾種算法中選擇一種废菱;避免使用難以維護的多重條件選擇語句;希望在具體策略類中封裝算法和與相關(guān)的數(shù)據(jù)結(jié)構(gòu)抖誉。


這篇博文相關(guān)的代碼
https://github.com/rainbowda/Design-Pattern/tree/master/dp-common/src/main/java/com/dp/strategy

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末殊轴,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子袒炉,更是在濱河造成了極大的恐慌旁理,老刑警劉巖,帶你破解...
    沈念sama閱讀 217,406評論 6 503
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件我磁,死亡現(xiàn)場離奇詭異孽文,居然都是意外死亡,警方通過查閱死者的電腦和手機夺艰,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,732評論 3 393
  • 文/潘曉璐 我一進店門芋哭,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人郁副,你說我怎么就攤上這事减牺。” “怎么了存谎?”我有些...
    開封第一講書人閱讀 163,711評論 0 353
  • 文/不壞的土叔 我叫張陵拔疚,是天一觀的道長。 經(jīng)常有香客問我既荚,道長稚失,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,380評論 1 293
  • 正文 為了忘掉前任恰聘,我火速辦了婚禮句各,結(jié)果婚禮上吸占,老公的妹妹穿的比我還像新娘。我一直安慰自己诫钓,他們只是感情好旬昭,可當我...
    茶點故事閱讀 67,432評論 6 392
  • 文/花漫 我一把揭開白布篙螟。 她就那樣靜靜地躺著菌湃,像睡著了一般。 火紅的嫁衣襯著肌膚如雪遍略。 梳的紋絲不亂的頭發(fā)上惧所,一...
    開封第一講書人閱讀 51,301評論 1 301
  • 那天,我揣著相機與錄音绪杏,去河邊找鬼下愈。 笑死,一個胖子當著我的面吹牛蕾久,可吹牛的內(nèi)容都是我干的势似。 我是一名探鬼主播,決...
    沈念sama閱讀 40,145評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼僧著,長吁一口氣:“原來是場噩夢啊……” “哼履因!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起盹愚,我...
    開封第一講書人閱讀 39,008評論 0 276
  • 序言:老撾萬榮一對情侶失蹤栅迄,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后皆怕,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體毅舆,經(jīng)...
    沈念sama閱讀 45,443評論 1 314
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,649評論 3 334
  • 正文 我和宋清朗相戀三年愈腾,在試婚紗的時候發(fā)現(xiàn)自己被綠了憋活。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 39,795評論 1 347
  • 序言:一個原本活蹦亂跳的男人離奇死亡虱黄,死狀恐怖悦即,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情礁鲁,我是刑警寧澤盐欺,帶...
    沈念sama閱讀 35,501評論 5 345
  • 正文 年R本政府宣布,位于F島的核電站仅醇,受9級特大地震影響冗美,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜析二,卻給世界環(huán)境...
    茶點故事閱讀 41,119評論 3 328
  • 文/蒙蒙 一粉洼、第九天 我趴在偏房一處隱蔽的房頂上張望节预。 院中可真熱鬧,春花似錦属韧、人聲如沸安拟。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,731評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽糠赦。三九已至,卻和暖如春锅棕,著一層夾襖步出監(jiān)牢的瞬間拙泽,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,865評論 1 269
  • 我被黑心中介騙來泰國打工裸燎, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留顾瞻,地道東北人。 一個月前我還...
    沈念sama閱讀 47,899評論 2 370
  • 正文 我出身青樓德绿,卻偏偏與公主長得像荷荤,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子移稳,可洞房花燭夜當晚...
    茶點故事閱讀 44,724評論 2 354

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

  • 目錄 本文的結(jié)構(gòu)如下: 引言 什么是策略模式 模式的結(jié)構(gòu) 典型代碼 代碼示例 策略模式和模板方法模式的區(qū)別 優(yōu)點和...
    w1992wishes閱讀 860評論 1 7
  • Android 自定義View的各種姿勢1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 172,109評論 25 707
  • 概念及定義 概念在完成某一功能時蕴纳,有時需要根據(jù)不同環(huán)境采取不同的策略或行為。將這些不同的策略或行為(稱為算法)一一...
    maxwellyue閱讀 532評論 0 0
  • 插一籃花 帶上笑容 送給自己
    靜軒茶香閱讀 182評論 1 1
  • 要說些什么呢秒裕!忘記了袱蚓!在一片狼藉得腦瓜子中,希望得到或者能看到什么几蜻! 可是什么都沒有喇潘,只有一片寂靜!感到現(xiàn)在的時光...
    違心一點都笑不起來閱讀 164評論 0 0