學(xué)好設(shè)計(jì)模式防被祭天:策略模式

策略模式

為了防止被“殺”了祭天昔头,學(xué)點(diǎn)設(shè)計(jì)模式伊群,并總結(jié)下還是有必要的。

一:理解

  1. 對象包含策略策精,可以根據(jù)不同對象的策略舰始,執(zhí)行不同的操作。
  2. 就像店家給不同等級(jí)的會(huì)員不同的折扣咽袜,其實(shí)是用不同的策略來為客戶服務(wù)丸卷。
  3. 策略模式和行為模式類似。


二:例子

你是個(gè)富二代询刹,你有很多朋友谜嫉。

今天,你要在家宴請自己的好朋友凹联。由于朋友太多沐兰,你記不全,但又希望給對方一種很親密的感覺蔽挠,和每個(gè)來賓都打招呼住闯。

大型派對

于是你叫來了程序員小菜幫你解決這個(gè)打招呼問題。

小菜一來就新建一個(gè)朋友類澳淑,朋友有名字屬性比原。

@Data
public class Friend {
    private String name;

    public Friend(String name) {
        this.name = name;
    }
}

為了方便記憶,你讓小菜把把朋友分成四類杠巡,分別是:

  1. 普通朋友
  2. 前女友
  3. 領(lǐng)導(dǎo)
  4. 老板

小菜分別為每類朋友建立了對應(yīng)的類量窘。

// 普通朋友
public class OrdinaryFriend extends Friend {
    public OrdinaryFriend(String name) {
        super(name);
    }
}

// 前女友
public class ExGirlFriend extends Friend {
    public ExGirlFriend(String name) {
        super(name);
    }
}

// 領(lǐng)導(dǎo)
public class Leader extends Friend {
    public Leader(String name) {
        super(name);
    }
}

// 老板
public class Boss extends Friend {
    public Boss(String name) {
        super(name);
    }
}

今晚,你將用不同的方式和不同類的朋友打招呼氢拥。

小菜幫你設(shè)計(jì)的程序使用if else來判斷來賓的類別蚌铜,并輸出不同的打招呼語句。

看了小菜寫的代碼兄一,你覺得沒什么問題厘线,而且還用到了instanceof這個(gè)你沒見過的運(yùn)算符,覺得小菜還是可以委以重任的出革。

public class Client {
    public static void main(String[] args) {
        System.out.println("派對開始,開始和來賓寒暄!");
        OrdinaryFriend ordinaryFriend = new OrdinaryFriend("Peter");
        greet(ordinaryFriend);
        ExGirlFriend exGirlFriend = new ExGirlFriend("Mary");
        greet(exGirlFriend);
        Leader leader = new Leader("Obama");
        greet(leader);
        Boss boss = new Boss("Jack");
        greet(boss);
    }

    public static void greet(Friend friend) {
        if (friend instanceof OrdinaryFriend) {
            System.out.println("等著對方打招呼,就是這么高貴,優(yōu)雅!");
        } else if (friend instanceof ExGirlFriend) {
            System.out.println(friend.getName() + ",你是不是還是放不下我?");
        } else if (friend instanceof Leader) {
            System.out.println("尊敬的" + friend.getName() + ",您好!");
        } else if (friend instanceof Boss) {
            System.out.println("尊敬的" + friend.getName() + ",您好!");
        }
    }
}

派對開始,開始和來賓寒暄!
等著對方打招呼,就是這么高貴,優(yōu)雅!
Mary,你是不是還是放不下我?
尊敬的Obama,您好!
尊敬的Jack,您好!

派對順利地結(jié)束了造壮,你和每位來賓都打了招呼。

然而,隨著你的生意越做越大耳璧,朋友越來越多成箫,地位也越來越高,你需要時(shí)不時(shí)地添加和修改打招呼的方法旨枯。

于是蹬昌,程序員小菜再一次徜徉在修改if else的海洋中。

小菜想攀隔,如果為每個(gè)朋友發(fā)一張身份卡皂贩,掛在胸前,主人看到身份卡就能知道該如何打招呼昆汹。

于是明刷,小菜將打招呼程序進(jìn)行重構(gòu),為每個(gè)朋友發(fā)了一張身份卡满粗,即greet方法辈末。

@Data
public abstract class Friend {
    private String name;

    public Friend(String name) {
        this.name = name;
    }

    public abstract void greet();
}

Friend基類變成了抽象類,申明了greet方法映皆,具體實(shí)現(xiàn)交給子類挤聘。

// 普通朋友
public class OrdinaryFriend extends Friend {
    public OrdinaryFriend(String name) {
        super(name);
    }

    @Override
    public void greet() {
        System.out.println("等著對方打招呼,就是這么高貴,優(yōu)雅!");
    }
}

// 前女友
public class ExGirlFriend extends Friend {
    public ExGirlFriend(String name) {
        super(name);
    }

    @Override
    public void greet() {
        System.out.println(getName() + ",你是不是還是放不下我?");
    }
}

// 領(lǐng)導(dǎo)
public class Leader extends Friend {
    public Leader(String name) {
        super(name);
    }

    @Override
    public void greet() {
        System.out.println("尊敬的" + getName() + ",您好!");
    }
}

// 老板
public class Boss extends Friend {
    public Boss(String name) {
        super(name);
    }

    @Override
    public void greet() {
        System.out.println("尊敬的" + getName() + ",您好!");
    }
}

打招呼時(shí)直接調(diào)用來賓的greet方法即可。

public class Client {
    public static void main(String[] args) {
        System.out.println("派對開始,開始和來賓寒暄!");
        OrdinaryFriend ordinaryFriend = new OrdinaryFriend("Peter");
        greet(ordinaryFriend);
        ExGirlFriend exGirlFriend = new ExGirlFriend("Mary");
        greet(exGirlFriend);
        Leader leader = new Leader("Obama");
        greet(leader);
        Boss boss = new Boss("Jack");
        greet(boss);
    }

    // 直接調(diào)用來賓的greet方法即可
    public static void greet(Friend friend) {
        friend.greet();
    }
}

為了更加精細(xì)地管理自己的朋友圈捅彻,你將自己的朋友圈分組表發(fā)給了小菜组去。

并且你最近學(xué)了英語,希望和某一類朋友(領(lǐng)導(dǎo)/老板等)打招呼的時(shí)候沟饥,使用英語添怔。

小菜發(fā)現(xiàn),雖然你的朋友類別增加到了一百類贤旷,但打招呼的方式只有固定不變的三種广料。

例子中和領(lǐng)導(dǎo)老板打招呼的方式一樣,將打招呼方式修改成英語時(shí)幼驶,需要修改多個(gè)類的greet方法艾杏。

小菜整理了打招呼的策略,整理出三種:

  1. 裝作沒看到策略盅藻,NoSeeStrategy
  2. 前女友后悔策略购桑,ExStrategy
  3. 尊敬策略,RespectStrategy

于是氏淑,小菜采用策略模式勃蜘,提取出一個(gè)策略接口,申明了greet方法假残。

并實(shí)現(xiàn)了三種打招呼策略類缭贡。

// 招呼策略接口
public interface GreetStrategy {
    void greet();
}

// 裝作沒看到策略
public class NoSeeStrategy implements GreetStrategy {
    @Override
    public void greet() {
        System.out.println("等著對方打招呼,就是這么高貴,優(yōu)雅!");
    }
}

// 前女友后悔策略
public class ExStrategy implements GreetStrategy {
    @Override
    public void greet() {
        System.out.println("你是不是還是放不下我?");
    }
}

// 尊敬策略
public class RespectStrategy implements GreetStrategy {
    @Override
    public void greet() {
        System.out.println("尊敬的客人, 您好!");
    }
}

修改朋友類炉擅,為朋友加上GreetStrategy屬性。

在普通朋友的構(gòu)造器中阳惹,直接set裝作沒看見策略NoSeeStrategy谍失。

其他幾類類似,不再給出莹汤。

@Data
public class Friend {
    private String name;
    private GreetStrategy greetStrategy;

    public Friend(String name) {
        this.name = name;
    }

    public void greet() {
        greetStrategy.greet();
    }
}

// 普通朋友類
public class OrdinaryFriend extends Friend {
    // 在構(gòu)造器中快鱼,直接setGreetStrategy
    public OrdinaryFriend(String name) {
        super(name);
        setGreetStrategy(new NoSeeStrategy());
    }
}

和朋友打招呼時(shí),其實(shí)調(diào)用的是打招呼策略的greet方法纲岭。

用了策略模式之后抹竹,修改和領(lǐng)導(dǎo)/老板打招呼的方法時(shí),不用再同時(shí)修改兩個(gè)類止潮,只需修改RespectStrategy即可柒莉。

public class RespectStrategy implements GreetStrategy {
    @Override
    public void greet() {
        System.out.println("Dear guests, nice to meet you!");
    }
}

于是,小菜開心地下班了沽翔。

下班了


三:再理解

  1. 策略模式是對繼承體系的一種再思考。繼承體系中窿凤,使用重寫來表示不同子類的不同策略仅偎,這些策略往往會(huì)重復(fù),提取這些策略雳殊,并新建對應(yīng)的策略類橘沥。
  2. 策略模式可以避免多次修改,也可以很方便地新增新的策略夯秃。
  3. 由于朋友子類中的setGreetStrategy是public的座咆,可以臨場修改打招呼的策略,將新的策略set進(jìn)去即可仓洼。
  4. 策略模式也稱為行為模式介陶,只是分析問題的角度不一樣。
  5. 行為模式例子:你是個(gè)富二代色建,你有十類女友哺呜,包括嬌小型,淑女型箕戳,熟女型等某残,她們都有papapa的行為,但精通的姿勢不一樣陵吸。由于你的女友實(shí)在太多玻墅,每次papapa的時(shí)候,你需要在腦子里執(zhí)行n多個(gè)if else壮虫,才能決定使用哪種姿勢澳厢。于是你決定讓每個(gè)女友都自帶papapa()方法,在成長的時(shí)候,直接調(diào)用女友的papapa方法即可赏酥。和打招呼一樣喳整,你發(fā)現(xiàn)雖然你有十類女友,但她們papapa的姿勢只有三種裸扶,分別是姿勢A框都,姿勢B和姿勢C,于是你抽象出了三種PapapaBehavior呵晨,女友們都持有PapapaBehavior對象魏保。每次你想開發(fā)新的papapa姿勢時(shí),不用再修改多個(gè)女友類摸屠,只需新增一個(gè)papapa行為類即可谓罗。
  6. 不同的papapa姿勢對于你而言是策略,而對于女朋友們而言是行為季二。
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末檩咱,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子胯舷,更是在濱河造成了極大的恐慌刻蚯,老刑警劉巖,帶你破解...
    沈念sama閱讀 222,183評(píng)論 6 516
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件桑嘶,死亡現(xiàn)場離奇詭異炊汹,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)逃顶,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,850評(píng)論 3 399
  • 文/潘曉璐 我一進(jìn)店門讨便,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人以政,你說我怎么就攤上這事霸褒。” “怎么了妙蔗?”我有些...
    開封第一講書人閱讀 168,766評(píng)論 0 361
  • 文/不壞的土叔 我叫張陵傲霸,是天一觀的道長。 經(jīng)常有香客問我眉反,道長昙啄,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 59,854評(píng)論 1 299
  • 正文 為了忘掉前任寸五,我火速辦了婚禮梳凛,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘梳杏。我一直安慰自己韧拒,他們只是感情好淹接,可當(dāng)我...
    茶點(diǎn)故事閱讀 68,871評(píng)論 6 398
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著叛溢,像睡著了一般塑悼。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上楷掉,一...
    開封第一講書人閱讀 52,457評(píng)論 1 311
  • 那天厢蒜,我揣著相機(jī)與錄音,去河邊找鬼烹植。 笑死斑鸦,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的草雕。 我是一名探鬼主播巷屿,決...
    沈念sama閱讀 40,999評(píng)論 3 422
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼墩虹!你這毒婦竟也來了嘱巾?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,914評(píng)論 0 277
  • 序言:老撾萬榮一對情侶失蹤诫钓,失蹤者是張志新(化名)和其女友劉穎浓冒,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體尖坤,經(jīng)...
    沈念sama閱讀 46,465評(píng)論 1 319
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,543評(píng)論 3 342
  • 正文 我和宋清朗相戀三年闲擦,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了慢味。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 40,675評(píng)論 1 353
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡墅冷,死狀恐怖纯路,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情寞忿,我是刑警寧澤驰唬,帶...
    沈念sama閱讀 36,354評(píng)論 5 351
  • 正文 年R本政府宣布,位于F島的核電站腔彰,受9級(jí)特大地震影響叫编,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜霹抛,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 42,029評(píng)論 3 335
  • 文/蒙蒙 一搓逾、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧杯拐,春花似錦霞篡、人聲如沸世蔗。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,514評(píng)論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽污淋。三九已至,卻和暖如春余掖,著一層夾襖步出監(jiān)牢的瞬間寸爆,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,616評(píng)論 1 274
  • 我被黑心中介騙來泰國打工浊吏, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留而昨,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 49,091評(píng)論 3 378
  • 正文 我出身青樓找田,卻偏偏與公主長得像歌憨,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個(gè)殘疾皇子墩衙,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,685評(píng)論 2 360

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