設(shè)計(jì)模式:策略模式,Java集合定制排序的核心思想

前言

前陣子面試的時(shí)候瞄勾,有個(gè)面試官問(wèn)我了解哪些設(shè)計(jì)模式嗎费奸?我說(shuō)了策略模式。接著他問(wèn)有哪些場(chǎng)景應(yīng)用进陡,我又回答他jdk的集合工具類有個(gè)排序方法就用到了策略模式愿阐,也就是java.util包下的Collections類,該類中有個(gè)sort方法趾疚,我們可以自定義排序規(guī)則實(shí)現(xiàn)集合的定制排序缨历,這就是策略模式最直接的應(yīng)用,說(shuō)完之后他點(diǎn)點(diǎn)頭糙麦,料想對(duì)我的回答還是比較滿意吧辛孵,當(dāng)然我也只是在這道面試題上裝裝逼而已,畢竟最后面試結(jié)束時(shí)他說(shuō)了句請(qǐng)回去等消息吧赡磅。魄缚。。仆邓。

什么是策略模式

言歸正傳鲜滩,今天我們學(xué)習(xí)設(shè)計(jì)模式系列的策略模式,先了解下其定義节值。

策略模式徙硅,也叫政策模式,其思想是:定義一組算法搞疗,將每個(gè)算法都封裝起來(lái)嗓蘑,并且使它們之間可以互換须肆。它的最大特點(diǎn)是使得算法可以在不影響客戶端的情況下發(fā)生變化,從而改變不同的功能桩皿。就拿上面說(shuō)的 sort 方法舉例豌汇,該方法中接收一個(gè)Comparator接口的參數(shù),對(duì)sort 方法來(lái)說(shuō)泄隔,它并不關(guān)心Comparator接口的具體實(shí)現(xiàn)拒贱,只要我們傳入的參數(shù)是該接口類型的就好,這樣一來(lái)佛嬉,我們就可以自己去實(shí)現(xiàn)Comparator接口逻澳,在其實(shí)現(xiàn)類里定義我們想要的排序規(guī)則,比如對(duì)集合的某個(gè)字段做升序還是降序排列暖呕,這正是策略模式的直接應(yīng)用斜做。

寫段代碼簡(jiǎn)單表示一下:

public static void main(String[] args) {
   
    List<Integer> list1 = new ArrayList<>();
    list1.add(1);
    list1.add(20);
    list1.add(3);
    
    Collections.sort(list1, new Comparator<Integer>() {
        @Override
        public int compare(Integer o1, Integer o2) {
            return o1 - o2;
        }
    });

    System.out.println("升序=======" + list1.toString());

    Collections.sort(list1, new Comparator<Integer>() {
        @Override
        public int compare(Integer o1, Integer o2) {
            return o2 - o1;
        }
    });

    System.out.println("降序=======" + list1.toString());
}

組成

了解了策略模式的定義和例子后,我們看下策略模式的組成角色湾揽。

策略模式包含三個(gè)角色:

  • Strategy抽象策略角色 :策略瓤逼、算法家族的抽象,通常為接口库物,定義每個(gè)策略或算法必須具有的方法和屬性霸旗。用上面的集合排序舉例,該角色就對(duì)應(yīng)著Comparator接口艳狐。
  • ConcreteStrategy具體策略角色 :實(shí)現(xiàn)抽象策略中的操作定硝,該類含有具體的算法。也就是我們自定義的Comparator實(shí)現(xiàn)類毫目。
  • Context封裝角色 :它也叫做上下文角色蔬啡,內(nèi)部會(huì)持有一個(gè)抽象角色的引用,給客戶端調(diào)用镀虐。該角色就對(duì)應(yīng)著Collections工具類本身箱蟆,該類中持有對(duì)Comparator接口的引用,可以接收我們自定義的具體的實(shí)現(xiàn)類刮便。

通過(guò)這三個(gè)角色空猜,我們可以簡(jiǎn)單列出策略模式的類圖:


策略模式類圖.png

看的出來(lái),策略模式的類圖還是比較簡(jiǎn)單的恨旱,根據(jù)這張類圖辈毯,我們寫一下它的代碼實(shí)現(xiàn)吧。

通用類代碼

抽象策略角色:

public interface Strategy {
    //策略模式的算法規(guī)則
    public void doSomething();
}

具體的策略角色:

public class ConcreteStrategy1 implements Strategy {
    public void doSomething() {
        System.out.println("具體策略1的運(yùn)算法則");
    }
}

public class ConcreteStrategy2 implements Strategy {
    public void doSomething() {
        System.out.println("具體策略2的運(yùn)算法則");
    }
}

封裝角色:

public class Context {
    //抽象策略
    private Strategy strategy = null;

    //構(gòu)造函數(shù)設(shè)置具體策略 
    public Context(Strategy _strategy) {
        this.strategy = _strategy;
    }

    //封裝后的策略方法 
    public void doAnythinig() {
        this.strategy.doSomething();
    }
}

建好三個(gè)角色后搜贤,當(dāng)客戶端要調(diào)用時(shí)谆沃,先確定要使用哪種具體的策略,創(chuàng)建出對(duì)應(yīng)的策略角色對(duì)象仪芒,再傳進(jìn)封裝角色就可以了唁影,具體代碼如下:

public class Client {
    public static void main(String[] args) {
        //聲明一個(gè)具體的策略 
        Strategy strategy = new ConcreteStrategy1();
        //聲明上下文對(duì)象 
        Context context = new Context(strategy);
        //執(zhí)行封裝后的方法 
        context.doAnythinig();
    }
}

總結(jié)

策略模式的介紹就講到這里了耕陷,說(shuō)起來(lái),策略模式算是比較簡(jiǎn)單的設(shè)計(jì)模式了据沈,但它在實(shí)際項(xiàng)目中也用的比較多哟沫,舉個(gè)例子,我之前所在公司中有個(gè)項(xiàng)目就用到了策略模式锌介。

那個(gè)項(xiàng)目屬于電商類的系統(tǒng)嗜诀,每類商品都有自己的優(yōu)惠券,下單結(jié)算金額時(shí)需要計(jì)算商品和優(yōu)惠券的價(jià)格總和掏湾,這里有個(gè)比較頭疼的問(wèn)題裹虫,因?yàn)槊糠N類型的商品都有獨(dú)特的優(yōu)惠券肿嘲,如果用傳統(tǒng)的 if/else 判斷商品和優(yōu)惠券的種類的話融击,那么添加一種商品或優(yōu)惠券都會(huì)使得下單的結(jié)算邏輯都需要重新修改,這很明顯不符合開(kāi)閉原則雳窟。針對(duì)這種情況尊浪,我們采用了策略模式的思想,對(duì)代碼做了如下改造封救,

1拇涤、定義一個(gè)擁有商品和優(yōu)惠券屬性的抽象策略角色

2、同時(shí)針對(duì)每種類型的商品創(chuàng)建對(duì)應(yīng)的具體策略角色誉结,定義自己獨(dú)特的計(jì)算優(yōu)惠券策略

3鹅士、在下單結(jié)算的方法中,根據(jù)商品和優(yōu)惠券類型創(chuàng)建對(duì)應(yīng)的具體策略對(duì)象惩坑,把該對(duì)象傳入一個(gè)封裝角色后并調(diào)用結(jié)算金額的方法

這樣一來(lái)就可以根據(jù)不同商品和優(yōu)惠券種類計(jì)算出對(duì)應(yīng)的金額了掉盅,而且代碼的封裝變得更加的抽象,商品具體的策略之間互相獨(dú)立以舒,不會(huì)牽一發(fā)而動(dòng)全身趾痘,省心又省力。

以上就是策略模式的一個(gè)具體應(yīng)用蔓钟,當(dāng)然永票,策略模式的應(yīng)用還有很多,我也就簡(jiǎn)單介紹其中的一個(gè)使用場(chǎng)景滥沫,通過(guò)實(shí)際例子讓大家感受下設(shè)計(jì)模式的魅力侣集,畢竟養(yǎng)兵千日,用兵一時(shí)兰绣,我們學(xué)再多的理論知識(shí)不就是為了有一天能用到實(shí)際嗎世分?

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市狭魂,隨后出現(xiàn)的幾起案子罚攀,更是在濱河造成了極大的恐慌党觅,老刑警劉巖,帶你破解...
    沈念sama閱讀 212,029評(píng)論 6 492
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件斋泄,死亡現(xiàn)場(chǎng)離奇詭異杯瞻,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)炫掐,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,395評(píng)論 3 385
  • 文/潘曉璐 我一進(jìn)店門魁莉,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人募胃,你說(shuō)我怎么就攤上這事旗唁。” “怎么了痹束?”我有些...
    開(kāi)封第一講書(shū)人閱讀 157,570評(píng)論 0 348
  • 文/不壞的土叔 我叫張陵检疫,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我祷嘶,道長(zhǎng)屎媳,這世上最難降的妖魔是什么? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 56,535評(píng)論 1 284
  • 正文 為了忘掉前任论巍,我火速辦了婚禮烛谊,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘嘉汰。我一直安慰自己丹禀,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,650評(píng)論 6 386
  • 文/花漫 我一把揭開(kāi)白布鞋怀。 她就那樣靜靜地躺著双泪,像睡著了一般。 火紅的嫁衣襯著肌膚如雪接箫。 梳的紋絲不亂的頭發(fā)上攒读,一...
    開(kāi)封第一講書(shū)人閱讀 49,850評(píng)論 1 290
  • 那天,我揣著相機(jī)與錄音辛友,去河邊找鬼薄扁。 笑死,一個(gè)胖子當(dāng)著我的面吹牛废累,可吹牛的內(nèi)容都是我干的邓梅。 我是一名探鬼主播,決...
    沈念sama閱讀 39,006評(píng)論 3 408
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼邑滨,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼日缨!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起掖看,我...
    開(kāi)封第一講書(shū)人閱讀 37,747評(píng)論 0 268
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤匣距,失蹤者是張志新(化名)和其女友劉穎面哥,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體毅待,經(jīng)...
    沈念sama閱讀 44,207評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡尚卫,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,536評(píng)論 2 327
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了尸红。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片吱涉。...
    茶點(diǎn)故事閱讀 38,683評(píng)論 1 341
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖外里,靈堂內(nèi)的尸體忽然破棺而出推汽,到底是詐尸還是另有隱情彤恶,我是刑警寧澤逊朽,帶...
    沈念sama閱讀 34,342評(píng)論 4 330
  • 正文 年R本政府宣布到千,位于F島的核電站竭望,受9級(jí)特大地震影響挪圾,放射性物質(zhì)發(fā)生泄漏丛版。R本人自食惡果不足惜产捞,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,964評(píng)論 3 315
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望贼穆。 院中可真熱鬧,春花似錦兰粉、人聲如沸故痊。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 30,772評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)愕秫。三九已至,卻和暖如春焰络,著一層夾襖步出監(jiān)牢的瞬間戴甩,已是汗流浹背。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 32,004評(píng)論 1 266
  • 我被黑心中介騙來(lái)泰國(guó)打工闪彼, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留甜孤,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 46,401評(píng)論 2 360
  • 正文 我出身青樓畏腕,卻偏偏與公主長(zhǎng)得像缴川,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子描馅,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,566評(píng)論 2 349

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

  • 本文的主要內(nèi)容: 介紹策略模式 示例商場(chǎng)購(gòu)物打折策略的實(shí)現(xiàn) 策略模式總結(jié) 源碼分析策略模式的典型應(yīng)用Java Co...
    小旋鋒的簡(jiǎn)書(shū)閱讀 1,352評(píng)論 0 1
  • javascript設(shè)計(jì)模式與開(kāi)發(fā)實(shí)踐 設(shè)計(jì)模式 每個(gè)設(shè)計(jì)模式我們需要從三點(diǎn)問(wèn)題入手: 定義 作用 用法與實(shí)現(xiàn) 單...
    穿牛仔褲的蚊子閱讀 4,045評(píng)論 0 13
  • 第二天回到火葬場(chǎng)上班的時(shí)候把夸,場(chǎng)里的人們就在暗暗地交頭接耳了。 聽(tīng)場(chǎng)長(zhǎng)說(shuō)铭污,巫世奇竟然用高過(guò)普通征地一倍的價(jià)錢恋日,收購(gòu)了...
    繞飛閱讀 156評(píng)論 0 2
  • 一膀篮、秀改 爸爸優(yōu)點(diǎn):愛(ài)我、愛(ài)媽媽岂膳; 媽媽優(yōu)點(diǎn):愛(ài)我各拷、愛(ài)爸爸; 孫秀改優(yōu)點(diǎn):愛(ài)爸媽闷营、理解爸媽烤黍; 劉永輝優(yōu)點(diǎn):愛(ài)妻子,...
    麥田守望_6a6c閱讀 130評(píng)論 0 0
  • 這是我費(fèi)勁心思畫的畫傻盟,原諒我停在了這里速蕊。 來(lái)到查濟(jì)的第三天,到處是畫的影跡娘赴。學(xué)生的畫规哲,葫蘆的畫,水粉...
    玫瑰0閱讀 208評(píng)論 0 0