策略模式定義:
定義了策略族,可以理解成各種算法,然后把每個(gè)策略(算法)封裝起來选侨,讓它們之間可以互換掖鱼。此模式讓算法獨(dú)立于使用他的客戶。
設(shè)計(jì)模式之禪上用了下文的故事援制,講述策略模式:
在三國(guó)演義中锨用,我最佩服諸葛亮的地方不是因?yàn)樗闯雒]而有三分天下的預(yù)測(cè),也不是他在赤壁鏖戰(zhàn)中借東風(fēng)的法術(shù)隘谣,更不是他七擒七縱孟獲的策略增拥。那是什么呢?是他“氣死周瑜寻歧,罵死王朗”的氣度和風(fēng)范掌栅!想想看,你用“氣”能把一個(gè)輪胎打爆码泛,用“氣”槍能夠把路燈打碎猾封,但是要把跟你沒有任何血緣關(guān)系的人氣死有多困難呀,更何況是周瑜這種智慧型人物噪珊!
在諸葛亮氣周瑜的過程中晌缘,有一件事情:那就是周瑜賠了夫人又折兵這件事情。事情經(jīng)過是這樣的:孫權(quán)看劉備有雄起之意痢站,殺是不能殺了磷箕,那會(huì)惹天下人唾棄,就想個(gè)招兒挫他一下阵难,那有什么辦法呢岳枷?孫權(quán)有個(gè)妹妹——孫尚香,準(zhǔn)備招劉備做女婿呜叫,然后孫權(quán)想辦法把劉備軟禁起來空繁,孫權(quán)的想法還是很單純的嘛,就是不讓你劉備回西川朱庆,然后我東吳想干啥就干啥盛泡,奪荊州,吞西川也不是不可能的娱颊。東吳的想法是好的傲诵,無奈中間多了智謀無敵的諸葛亮,他早就預(yù)測(cè)了東吳有此招數(shù)维蒙,于是在劉備去東吳招親之前掰吕,特授以伴郎趙云三個(gè)錦囊果覆,說是按天機(jī)拆開解決棘手問題颅痊。
這三個(gè)妙計(jì)分別是:找喬國(guó)老幫忙(也就是走后門了),求吳國(guó)太放行(訴苦)以及孫夫人斷后局待,對(duì)這三個(gè)妙計(jì)不熟悉的讀者可以去溫習(xí)一下《三國(guó)演義》斑响,這里就不多說了菱属。想想看,這三個(gè)計(jì)謀有什么相似之處舰罚,他們都是告訴趙云要怎么執(zhí)行纽门,也就是說這三個(gè)計(jì)謀都有一個(gè)方法是執(zhí)行,具體執(zhí)行什么內(nèi)容营罢,每個(gè)計(jì)謀當(dāng)然不同了赏陵,分析到這里,我們是不是就有這樣一個(gè)設(shè)計(jì)思路:三個(gè)妙計(jì)應(yīng)該實(shí)現(xiàn)的是同一個(gè)接口饲漾?聰明蝙搔!
類圖如下:
代碼:
策略接口
public interface IStrategy {
//每個(gè)錦囊妙計(jì)都是一個(gè)可執(zhí)行的算法
public void operate();
}
策略一
public class BackDoor implements IStrategy {
public void operate() {
System.out.println("找喬國(guó)老幫忙,讓吳國(guó)太給孫權(quán)施加壓力");
}
策略二
public class GivenGreenLight implements IStrategy {
public void operate() {
System.out.println("求吳國(guó)太開綠燈,放行考传!");
}
策略三
public class BlockEnemy implements IStrategy {
public void operate() {
System.out.println("孫夫人斷后吃型,擋住追兵");
}
通過組合的方式把策略包裹,為使用人提供方便使用的類僚楞。在使用人使用策略時(shí)勤晚,方便動(dòng)態(tài)設(shè)定策略,并通過調(diào)用策略接口的統(tǒng)一方法觸發(fā)策略泉褐,這同時(shí)暴露了策略模式的弱點(diǎn)赐写,他要求使用者清楚每一個(gè)策略的運(yùn)用時(shí)機(jī)。在上面的故事中是有漏洞的膜赃,趙云并不知道何時(shí)應(yīng)該使用哪個(gè)策略血淌,是諸葛亮提前設(shè)定好的。
public class Context {
//構(gòu)造函數(shù)财剖,你要使用哪個(gè)妙計(jì)
private IStrategy straegy;
public Context(IStrategy strategy){
this.straegy = strategy;
}
//使用計(jì)謀了悠夯,看我出招了
public void operate(){
this.straegy.operate();
}
}
使用者
public class ZhaoYun {
//趙云出場(chǎng)了,他根據(jù)諸葛亮給他的交代躺坟,依次拆開妙計(jì)
public static void main(String[] args) {
Context context;
//剛剛到吳國(guó)的時(shí)候拆第一個(gè)
System.out.println("---剛剛到吳國(guó)的時(shí)候拆第一個(gè)---");
context = new Context(new BackDoor()); //拿到妙計(jì)
context.operate(); //拆開執(zhí)行
System.out.println("\n\n\n\n\n\n\n\n");
//劉備樂不思蜀了沦补,拆第二個(gè)了
System.out.println("---劉備樂不思蜀了,拆第二個(gè)了---");
context = new Context(new GivenGreenLight());
context.operate(); //執(zhí)行了第二個(gè)錦囊
System.out.println("\n\n\n\n\n\n\n\n");
//孫權(quán)的小兵追來了咪橙,咋辦夕膀?拆第三個(gè)
System.out.println("---孫權(quán)的小兵追來了,咋辦美侦?拆第三個(gè)---");
context = new Context(new BlockEnemy());
context.operate(); //孫夫人退兵
System.out.println("\n\n\n\n\n\n\n\n");
}
}
整個(gè)故事的類圖
策略模式優(yōu)點(diǎn)
- 可以自由切換算法
- 避免了多條件的判斷
- 擴(kuò)展性好可以定義新的算法提供給使用者
策略模式缺點(diǎn)
- 算法類數(shù)量增多产舞,每個(gè)算法都是一個(gè)類
- 算法要對(duì)外安全暴露,因?yàn)槭褂谜邅頉Q定是用哪個(gè)算法菠剩,必然要了解算法內(nèi)部做了什么易猫。
可以使用其他模式來修正這個(gè)缺陷,如工廠方法模式具壮、代理模式或享元模式准颓。(書上寫的哈蝇,還不了解實(shí)際結(jié)合)
策略模式相對(duì)簡(jiǎn)單。運(yùn)用感悟以后再更新吧攘已。