設(shè)計模式之——策略模式(Strategy Pattern)及在Android中的應(yīng)用

相信大家都用過計算器玷过,輸入一個數(shù)苛蒲,然后輸入運算符卤橄,然后再輸入一個數(shù),就會根據(jù)不同的運算符做不同的運算臂外。

最直接的加減法:

public class Calculator {
    //加符號
    private final static String ADD_SYMBOL = "+";
    //減符號
    private final static String SUB_SYMBOL = "-";
    public int exec(int a,int b,String symbol){
        int result =0;
        if(symbol.equals(ADD_SYMBOL)){
            result = this.add(a, b);
        }else if(symbol.equals(SUB_SYMBOL)){
            result = this.sub(a, b);
        }
        return result;
    }
    //加法運算
    private int add(int a,int b){
        return a+b;
    }
    //減法運算
    private int sub(int a,int b){
        return a-b;
    }
}

用戶使用:

public class Client {
    public static void main(String[] args) {
        //輸入的兩個參數(shù)是數(shù)字
        int a = Integer.parseInt(args[0]);
        String symbol = args[1]; //符號
        int b = Integer.parseInt(args[2]);
        System.out.println("輸入的參數(shù)為:"+Arrays.toString(args));
        //生成一個運算器
        Calculator cal = new Calculator();
        System.out.println("運行結(jié)果為:"+a + symbol + b + "=" + cal.exec(a, b, symbol));
    }
}

這是最簡單直接的代碼窟扑,有什么問題嗎?假如用戶需要這個計算器支持乘法呢漏健?就要改Calculator類嚎货,明顯違背了開閉原則,系統(tǒng)也不利于維護蔫浆。

那么怎么設(shè)計成可以擴展的代碼呢殖属?就需要策略模式了。

策略模式類圖

定義:策略模式也叫政策模式瓦盛,定義一組算法洗显,將每個算法都封裝起來,并且使它們之間可以互換原环。

這個定義是非常明確挠唆、清晰的,“定義一組算法”扮念,看看加減法和乘法是不是三個算
法损搬?“將每個算法都封裝起來”,那么我們定義一個類柜与,封裝算法巧勤,可以互換,是不是多態(tài)的特征呢弄匕?我們用代碼把這個定義實現(xiàn)下:

//抽象策略
interface Calculator {
    public int exec(int a,int b);
}
// 具體策略

public class Add implements Calculator {
    // 加法運算
    public int exec(int a, int b) {
        return a+b;
    }
}
public class Sub implements Calculator {
    //減法運算
    public int exec(int a, int b) {
        return a-b;
    }
}

策略定義好了颅悉,然后定義一個Context封裝類,其作用是承裝三個策略迁匠,根據(jù)不同的需要替換:

public class Context {
    private Calculator cal = null;
    public Context(Calculator _cal){
        this.cal = _cal;
    }
    public int exec(int a,int b,String symbol){
        return this.cal.exec(a, b);
    }
}

用戶使用:

public class Client {
    //加符號
    public final static String ADD_SYMBOL = "+";
    //減符號
    public final static String SUB_SYMBOL = "-";
    public static void main(String[] args) {
        //輸入的兩個參數(shù)是數(shù)字
        int a = Integer.parseInt(args[0]);
        String symbol = args[1]; //符號
        int b = Integer.parseInt(args[2]);
        System.out.println("輸入的參數(shù)為:"+Arrays.toString(args));
        //上下文
        Context context = null;
        //判斷初始化哪一個策略
        if(symbol.equals(ADD_SYMBOL)){
            context = new Context(new Add());
        }else if(symbol.equals(SUB_SYMBOL)){
            context = new Context(new Sub());
        }
        System.out.println("運行結(jié)果為:"+a+symbol+b+"="+context.exec(a,b,symbol));
    }
}

需要增加乘法呢剩瓶?實現(xiàn)Calculator ,增加乘法算法城丧,直接替換就ok了:

public class Mul implements Calculator {
    //乘法運算
    public int exec(int a, int b) {
        return a*b;
    }
}

public class Client {
    //加符號
    public final static String ADD_SYMBOL = "+";
    //減符號
    public final static String SUB_SYMBOL = "-";
    //乘符號
    public final static String MUL_SYMBOL = "*";
    public static void main(String[] args) {
        //輸入的兩個參數(shù)是數(shù)字
        int a = Integer.parseInt(args[0]);
        String symbol = args[1]; //符號
        int b = Integer.parseInt(args[2]);
        System.out.println("輸入的參數(shù)為:"+Arrays.toString(args));
        //上下文
        Context context = null;
        //判斷初始化哪一個策略
        if(symbol.equals(ADD_SYMBOL)){
            context = new Context(new Add());
        }else if(symbol.equals(SUB_SYMBOL)){
            context = new Context(new Sub());
        }else if(symbol.equals(MUL_SYMBO)){
            context = new Context(new Mul());
        }
        System.out.println("運行結(jié)果為:"+a+symbol+b+"="+context.exec(a,b,symbol));
    }
}

我們總結(jié)下這樣的寫的優(yōu)點:

  • 算法可以自由切換
    這是策略模式本身定義的延曙,只要實現(xiàn)抽象策略,它就成為策略家族的一個成員亡哄,通過封
    裝角色對其進行封裝枝缔,保證對外提供“可自由切換”的策略。
  • 避免使用多重條件判斷
    如果沒有策略模式,我們想想看會是什么樣子愿卸?一個策略家族有5個策略算法灵临,一會要
    使用A策略,一會要使用B策略趴荸,怎么設(shè)計呢儒溉?使用多重的條件語句?多重條件語句不易維
    護发钝,而且出錯的概率大大增強顿涣。使用策略模式后,可以由其他模塊決定采用何種策略酝豪,策略
    家族對外提供的訪問接口就是封裝類园骆,簡化了操作,同時避免了條件語句判斷寓调。
  • 擴展性良好
    這甚至都不用說是它的優(yōu)點,因為它太明顯了锄码。在現(xiàn)有的系統(tǒng)中增加一個策略太容易
    了夺英,只要實現(xiàn)接口就可以了,其他都不用修改滋捶,類似于一個可反復(fù)拆卸的插件痛悯,這大大地符合了OCP原則。

當(dāng)然他也不可避免的具有缺點:

  • 策略類數(shù)量增多
    每一個策略都是一個類重窟,復(fù)用的可能性很小载萌,類數(shù)量增多。
  • 所有的策略類都需要對外暴露
    上層模塊必須知道有哪些策略巡扇,然后才能決定使用哪一個策略扭仁,這與迪米特法則是相違
    背的,我只是想使用了一個策略厅翔,我憑什么就要了解這個策略呢乖坠?那要你的封裝類還有什么
    意義?這是原裝策略模式的一個缺點刀闷,幸運的是熊泵,我們可以使用其他模式來修正這個缺陷,
    如工廠方法模式甸昏、代理模式或享元模式顽分。

那我們什么應(yīng)該使用策略模式呢:

  • 多個類只有在算法或行為上稍有不同的場景。
  • 算法需要自由切換的場景施蜜。
    例如卒蘸,算法的選擇是由使用者決定的,或者算法始終在進化花墩,特別是一些站在技術(shù)前沿
    的行業(yè)悬秉,連業(yè)務(wù)專家都無法給你保證這樣的系統(tǒng)規(guī)則能夠存在多長時間澄步,在這種情況下策略
    模式是你最好的助手。
  • 需要屏蔽算法規(guī)則的場景和泌。
    現(xiàn)在的科技發(fā)展得很快村缸,人腦的記憶是有限的(就目前來說是有限的),太多的算法你
    只要知道一個名字就可以了武氓,傳遞相關(guān)的數(shù)字進來梯皿,反饋一個運算結(jié)果,萬事大吉县恕。

Android中有一個需求場景是不是特別像东羹?有數(shù)據(jù)的時候,要展示數(shù)據(jù)忠烛;無網(wǎng)絡(luò)的時候属提,展示重試界面。對的美尸,就是狀態(tài)策略冤议,根據(jù)不同的狀態(tài)選取不同的策略,但是我們一般不單獨使用策略模式师坎,而是使用工廠方法來實現(xiàn)策略類的聲明恕酸。也就是利用混編,揚長避短胯陋,達(dá)到最優(yōu)的設(shè)計蕊温。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市遏乔,隨后出現(xiàn)的幾起案子义矛,更是在濱河造成了極大的恐慌,老刑警劉巖盟萨,帶你破解...
    沈念sama閱讀 222,464評論 6 517
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件症革,死亡現(xiàn)場離奇詭異,居然都是意外死亡鸯旁,警方通過查閱死者的電腦和手機噪矛,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 95,033評論 3 399
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來铺罢,“玉大人艇挨,你說我怎么就攤上這事【伦福” “怎么了缩滨?”我有些...
    開封第一講書人閱讀 169,078評論 0 362
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經(jīng)常有香客問我脉漏,道長苞冯,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 59,979評論 1 299
  • 正文 為了忘掉前任侧巨,我火速辦了婚禮舅锄,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘司忱。我一直安慰自己皇忿,他們只是感情好,可當(dāng)我...
    茶點故事閱讀 69,001評論 6 398
  • 文/花漫 我一把揭開白布坦仍。 她就那樣靜靜地躺著鳍烁,像睡著了一般。 火紅的嫁衣襯著肌膚如雪繁扎。 梳的紋絲不亂的頭發(fā)上幔荒,一...
    開封第一講書人閱讀 52,584評論 1 312
  • 那天,我揣著相機與錄音梳玫,去河邊找鬼铺峭。 笑死,一個胖子當(dāng)著我的面吹牛汽纠,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播傀履,決...
    沈念sama閱讀 41,085評論 3 422
  • 文/蒼蘭香墨 我猛地睜開眼虱朵,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了钓账?” 一聲冷哼從身側(cè)響起碴犬,我...
    開封第一講書人閱讀 40,023評論 0 277
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎梆暮,沒想到半個月后服协,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 46,555評論 1 319
  • 正文 獨居荒郊野嶺守林人離奇死亡啦粹,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 38,626評論 3 342
  • 正文 我和宋清朗相戀三年偿荷,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片唠椭。...
    茶點故事閱讀 40,769評論 1 353
  • 序言:一個原本活蹦亂跳的男人離奇死亡跳纳,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出贪嫂,到底是詐尸還是另有隱情寺庄,我是刑警寧澤,帶...
    沈念sama閱讀 36,439評論 5 351
  • 正文 年R本政府宣布,位于F島的核電站斗塘,受9級特大地震影響赢织,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜馍盟,卻給世界環(huán)境...
    茶點故事閱讀 42,115評論 3 335
  • 文/蒙蒙 一于置、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧朽合,春花似錦俱两、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,601評論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至讲婚,卻和暖如春尿孔,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背筹麸。 一陣腳步聲響...
    開封第一講書人閱讀 33,702評論 1 274
  • 我被黑心中介騙來泰國打工活合, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人物赶。 一個月前我還...
    沈念sama閱讀 49,191評論 3 378
  • 正文 我出身青樓白指,卻偏偏與公主長得像,于是被迫代替她去往敵國和親酵紫。 傳聞我的和親對象是個殘疾皇子告嘲,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 45,781評論 2 361

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

  • 【學(xué)習(xí)難度:★☆☆☆☆,使用頻率:★★★★☆】直接出處:策略模式梳理和學(xué)習(xí):https://github.com/...
    BruceOuyang閱讀 1,468評論 3 5
  • 工廠模式類似于現(xiàn)實生活中的工廠可以產(chǎn)生大量相似的商品奖地,去做同樣的事情橄唬,實現(xiàn)同樣的效果;這時候需要使用工廠模式。簡單...
    舟漁行舟閱讀 7,777評論 2 17
  • javascript設(shè)計模式與開發(fā)實踐 設(shè)計模式 每個設(shè)計模式我們需要從三點問題入手: 定義 作用 用法與實現(xiàn) 單...
    穿牛仔褲的蚊子閱讀 4,069評論 0 13
  • 1.初識策略模式 定義一系列的算法参歹,把它們一個個封裝起來仰楚,并且使它們可相互替換。本模式使得算法可獨立于使用它的客戶...
    王偵閱讀 1,462評論 0 3
  • 今天休息犬庇。這是把清明小長假提前休了一天僧界。也好,分散休息臭挽,不至于一下子歇得無聊捎泻。 原本打算出去踏踏青,感受一下春光埋哟。...
    陽覓閱讀 160評論 0 2