設(shè)計模式Java語言實現(xiàn)之策略模式(生動有趣版)

策略模式:

前言:

作者:韓數(shù)

Github:https://github.com/hanshuaikang

時間:2019-01-26

JDK版本:1.8

定義:

定義一系列的算法,把它們一個個封裝起來,并且使它們可相互替換沙峻。本模式使得算法可獨(dú)立于使用它的客戶而變化拟蜻。

適用范圍:

1.在一個系統(tǒng)中驯击,有很多相似的類产园,而區(qū)分這些類的僅僅是不同的行為。那么策略模式可以像電腦主機(jī)一樣模塊化的讓一個對象在不同的行為中選擇一種一種行為落君。

2护糖、一個系統(tǒng)需要動態(tài)地在幾種算法中選擇一種国觉。

3、如果一個對象有很多的行為又憨,如果不用恰當(dāng)?shù)哪J酱浠簦@些行為就只好使用多重的條件選擇語句來實現(xiàn)。

優(yōu)缺點(diǎn):

優(yōu)點(diǎn):

代碼耦合度比較底蠢莺,相對來說比較靈活一些

可以避免使用if else多重判斷語句

比較有彈性壶运,可擴(kuò)展性比較好

缺點(diǎn)

策略類會比較多,之后的代碼實戰(zhàn)中會發(fā)現(xiàn)這個問題

所有策略類都需要對外暴露

前提引入:

韓數(shù)獨(dú)創(chuàng)之對話流:

老板: 阿呆浪秘,你去給我編寫一個鴨子類(嚴(yán)重吐槽蒋情,請大家不要想歪,本書依靠head frist系列書籍耸携,為了避免讀者讀書的時候代碼和書籍有不同的地方影響理解棵癣,故沒有修正)

阿呆: 內(nèi)心戲(不就寫個實體類嗎。寫個Duck類夺衍,然后把鴨子外貌狈谊,飛,叫這樣的特征定義了,方法實現(xiàn)了就OK了,Nice,完美)河劝,老板沒問題壁榕,保證完成任務(wù)!

a week has later.... 阿呆信心滿滿的把寫好的Duck類交給了老板赎瞎。

老板: 不錯牌里,寫的不錯,哎呀务甥,可是牡辽,我突然又想要一只橡皮鴨,這只鴨子敞临,不會飛态辛,吱吱叫,我小時候最喜歡的玩具挺尿,這樣吧奏黑,你去寫寫這個啥橡皮鴨吧。

阿呆:(內(nèi)心戲: 這橡皮鴨编矾,這熟史,跟我上次寫的那個鴨子不是一個品種啊,怎么還吱吱叫洽沟,鴨子不都嘎嘎嘎叫嗎以故,算了,不就是再寫一個類繼承Duck類嗎裆操,把fly怒详,quack,display這三個方法覆蓋重寫了就好了踪区,Nice昆烁,完美,我簡直是一個天才6懈凇)老板沒問題静尼,保證完成任務(wù)!

a week has later.... 阿呆信心滿滿的把寫好的RubberDuck類交給了老板传泊。

老板: 不錯鼠渺,真好,對了眷细,阿呆呀拦盹,我那個侄女,她喜歡那個綠毛鴨溪椎,會飛普舆,咕咕叫恬口,頭上長綠毛的那種,你看能寫么沼侣?

阿呆:(內(nèi)心戲:MMP祖能,略) 老板沒問題,保證完成任務(wù)蛾洛!

a week has later...

老板: 那個黑天鴨...

阿呆:(內(nèi)心戲:emmmmmp) 老板沒問題养铸,保證完成任務(wù)!

老板: 那個七小天鴨...

阿呆:(內(nèi)心戲:emmmmmp) 老板沒問題雅潭,保證完成任務(wù)揭厚!

老板: 那個派大鴨...

阿呆:(內(nèi)心戲:emmmmmp) 老板沒問題却特,保證完成任務(wù)扶供!

a year has later...

阿呆:卒

這么玩兒下去肯定不行,只通過繼承裂明,必然可以完成老板的要求椿浓,萬一有一萬只不同品種的鴨子,不敢往下想了闽晦,而且Duck是所有類的父類扳碍,這要是Duck改一點(diǎn)點(diǎn),想到后面還有幾萬個Duck的孩子要改仙蛉,不禁倒吸一口涼氣笋敞,這是,阿呆的弟弟二呆出場了荠瘪,說:

這世間鴨子千千萬夯巷,不過數(shù)種,記得我之前給你講那個電腦主機(jī)的故事么哀墓,把所有零件設(shè)計成可拆卸更換的模塊

只留下那個大家通用的模塊不要動趁餐,在鴨子身上就是游泳,哪種鴨子不會游泳篮绰?你說后雷,其他的,飛呀吠各,叫什么的臀突,我們單獨(dú)分離出來,最后老板要啥鴨子贾漏,我們給他組裝一下不就得了候学。

此時,設(shè)計模式中一句寶典浮出水面磕瓷,那就是:分離變和不變的部分盒齿。

大家聽了不禁嘖嘖稱贊念逞,紛紛嘆道妙呀,妙呀边翁,真是妙棒岢小!

代碼實戰(zhàn):

煥然一新后的鴨子類:

public abstract class Duck {
?
 /*
 * 面向超類編程符匾,主類Duck只保留所有鴨子通用不變的特征比如游泳
 * 變化的部分單獨(dú)封裝叨咖,提高代碼的彈性,避免因為單一的向下繼承
 * 造成的代碼的靈活性降低啊胶,避免過于耦合情況的發(fā)生甸各。
 */

 FlyBehavior flyBehavior;
 QuackBehavior quackBehavior;

 public Duck() {
 }

 //定義set方法,可以動態(tài)的設(shè)定鴨子飛行的行為
 public void setFlyBehavior (FlyBehavior fb) {
 flyBehavior = fb;
 }

 //定義set方法焰坪,可以動態(tài)的設(shè)定鴨子飛行的行為
 public void setQuackBehavior(QuackBehavior qb) {
 quackBehavior = qb;
 }

 //鴨子的外表趣倾,這里定義為抽象方法,父類只做聲明某饰,不負(fù)責(zé)實現(xiàn)
 abstract void display();

 //鴨子的行為儒恋,Duck不適合實現(xiàn),交給相應(yīng)的模塊實現(xiàn)黔漂。
 public void performFly() {
 flyBehavior.fly();
 }

 public void performQuack() {
 quackBehavior.quack();
 }

 //所有鴨子都會游泳
 public void swim() {
 System.out.println("All ducks float, even decoys!");
 }
}

可能會有人不太懂诫尽,F(xiàn)lyBehavior flyBehavior; QuackBehavior quackBehavior;是什么意思,你想啊炬守,雖然顯卡,CPU牧嫉,音響,內(nèi)存條都模塊化了减途,但是也總的留個插頭方便接入不是酣藻。

定義飛行行為的接口,為啥是接口呢观蜗?不是類臊恋,面向接口(超類)編程,可以更好的利用面向?qū)ο笾械亩鄳B(tài)墓捻,第二個也可以提高程序相互調(diào)用中的安全性抖仅。提高程序的靈活性,可擴(kuò)展性砖第。

public interface FlyBehavior {
 public void fly();
}

同理叫聲接口:

public interface QuackBehavior {
 public void quack();
}

比如嘎嘎叫的鴨子撤卢,我們就定義一個Quack類實現(xiàn)QuackBehavior的接口,并編寫quack方法的實現(xiàn)為嘎嘎叫梧兼,吱吱叫的鴨子放吩,我們就定義一個Squeak類實現(xiàn)QuackBehavior的接口,并編寫quack方法的實現(xiàn)為吱吱叫羽杰,等等渡紫,咕咕叫到推,喔喔叫,哇我叫惕澎,等等等等等莉测,你開心就好。飛的行為同理唧喉。

/***
 * 
 * 定義鴨子叫聲是嘎嘎嘎的行為
 * 
 */
?
?
public class Quack implements QuackBehavior {
 public void quack() {
 System.out.println("嘎嘎嘎");
 }
}
?
?
?
/***
 * 
 * @author hansu
 * 定義鴨子吱吱叫的行為
 * 
 */
?
?
public class Squeak implements QuackBehavior {
 public void quack() {
 System.out.println("吱吱吱");
 }
}
?
/***
 * 
 * 定義鴨子不會飛的行為
 * 
 *
 */
?
public class FlyNoWay implements FlyBehavior {
 public void fly() {
 System.out.println("哎捣卤,難過,我不會飛");
 }
}
?
?
?
/***
 * 
 * 定義鴨子是會飛的行為
 *
 */
?
public class FlyWithWings implements FlyBehavior {
 public void fly() {
 System.out.println("我會飛!哈哈哈");
 }
}
?

好了八孝,現(xiàn)在模塊是寫好了董朝,可是,我們怎么樣編寫鴨子的子類把這些模塊裝上去呢干跛?二呆緩緩說子姜,急啥,且聽我娓娓道來驯鳖。

喲闲询,要是想把這些模塊來組裝

那你就要深入進(jìn)去它的心房

把模塊放入構(gòu)造器中

變成一把直接就上膛的手槍

yo久免,freestyle

比如橡皮鴨的特征是吱吱叫浅辙,不會飛,身子是橡皮做的阎姥,于是就把FlyNoWay记舆,Squeak模塊組裝一下,然后只需實現(xiàn)一下父類Duck的display方法就會得到一只嶄新的完全滿足甲方要求的橡皮鴨了呼巴!

如下:

/***
 * 
 * demo1:橡皮鴨泽腮,特征,不會飛衣赶,吱吱叫
 *
 */
?
public class RubberDuck extends Duck {

 public RubberDuck() {
 /*
 * 注:因為RubberDuck繼承Duck類诊赊,所有Duck類中定義的
 * flyBehavior和quackBehavior可以直接賦值
 */
 //定義橡皮鴨不會飛的行為
 flyBehavior = new FlyNoWay();
 //定義橡皮鴨吱吱叫的行為
 quackBehavior = new Squeak();
 }

 public void display() {
 System.out.println("我是一個橡皮鴨,我的身體是橡皮做噠");
 }
}

編寫測試代碼Text:

public class Text {

 public static void main(String[] args) {
 Text t = new Text();
 t.rubberDuckDemoText();

 System.out.println("\n現(xiàn)在有請活的鴨子閃亮登場府瞄!\n");

 t.liveDuckDemoText();
 }

 public void rubberDuckDemoText() {

 RubberDuck rubberDuck = new RubberDuck();
 rubberDuck.display();
 rubberDuck.performFly();
 rubberDuck.performQuack();
?

 }

 public void liveDuckDemoText() {

 LiveDuck liveDuck = new LiveDuck();
 liveDuck.display();
 liveDuck.performFly();
 liveDuck.performQuack();

 }

?
}

Out:

我是一個橡皮鴨碧磅,我的身體是橡皮做噠 I can't fly 吱吱吱

現(xiàn)在有請活的鴨子閃亮登場!

我是一只活鴨子 我會飛!哈哈哈 嘎嘎嘎

最后遵馆,二呆和老板幸福的生活在了一起鲸郊。

實戰(zhàn)總結(jié):

在這里大家就會發(fā)現(xiàn)了,雖然這樣的確比繼承單一Duck類重寫方法方便高效了很多货邓,但是如果鴨子特征超級多的話秆撮,也需要編寫超級多的行為類,同時换况,每個行為類都必須是可實例化的职辨,這針對某些情況來說并不太適合盗蟆,但是,設(shè)計模式有二十七種呢舒裤,更不要說其他設(shè)計模式了姆涩,更是多到數(shù)不勝數(shù),所以在合適的情況下選擇合適的設(shè)計模式可以顯著提高我們代碼的效率和質(zhì)量惭每,這點(diǎn)是毋庸置疑的骨饿。

寫在最后:

歡迎大家給小星星,您的星星是我寫下去的不竭動力台腥!

源碼部分請移步本人Github下載:

Github地址:

Github:https://github.com/hanshuaikang/design-pattern-java

參考資料:

菜鳥教程:http://www.runoob.com/design-pattern/strategy-pattern.html

Head frist of 設(shè)計模式

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末宏赘,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子黎侈,更是在濱河造成了極大的恐慌察署,老刑警劉巖,帶你破解...
    沈念sama閱讀 216,324評論 6 498
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件峻汉,死亡現(xiàn)場離奇詭異贴汪,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)休吠,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,356評論 3 392
  • 文/潘曉璐 我一進(jìn)店門扳埂,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人瘤礁,你說我怎么就攤上這事阳懂。” “怎么了柜思?”我有些...
    開封第一講書人閱讀 162,328評論 0 353
  • 文/不壞的土叔 我叫張陵岩调,是天一觀的道長。 經(jīng)常有香客問我赡盘,道長号枕,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,147評論 1 292
  • 正文 為了忘掉前任陨享,我火速辦了婚禮葱淳,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘霉咨。我一直安慰自己蛙紫,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,160評論 6 388
  • 文/花漫 我一把揭開白布途戒。 她就那樣靜靜地躺著坑傅,像睡著了一般。 火紅的嫁衣襯著肌膚如雪喷斋。 梳的紋絲不亂的頭發(fā)上唁毒,一...
    開封第一講書人閱讀 51,115評論 1 296
  • 那天蒜茴,我揣著相機(jī)與錄音,去河邊找鬼浆西。 笑死粉私,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的近零。 我是一名探鬼主播诺核,決...
    沈念sama閱讀 40,025評論 3 417
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼久信!你這毒婦竟也來了窖杀?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 38,867評論 0 274
  • 序言:老撾萬榮一對情侶失蹤裙士,失蹤者是張志新(化名)和其女友劉穎入客,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體腿椎,經(jīng)...
    沈念sama閱讀 45,307評論 1 310
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡桌硫,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,528評論 2 332
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了啃炸。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片铆隘。...
    茶點(diǎn)故事閱讀 39,688評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖肮帐,靈堂內(nèi)的尸體忽然破棺而出咖驮,到底是詐尸還是另有隱情,我是刑警寧澤训枢,帶...
    沈念sama閱讀 35,409評論 5 343
  • 正文 年R本政府宣布,位于F島的核電站忘巧,受9級特大地震影響恒界,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜砚嘴,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,001評論 3 325
  • 文/蒙蒙 一十酣、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧际长,春花似錦耸采、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,657評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至如绸,卻和暖如春嘱朽,著一層夾襖步出監(jiān)牢的瞬間旭贬,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,811評論 1 268
  • 我被黑心中介騙來泰國打工搪泳, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留稀轨,地道東北人。 一個月前我還...
    沈念sama閱讀 47,685評論 2 368
  • 正文 我出身青樓岸军,卻偏偏與公主長得像奋刽,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子艰赞,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,573評論 2 353

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

  • 本文參照《Head First 設(shè)計模式》杨名,轉(zhuǎn)載請注明出處對于整個系列,我們按照這本書的設(shè)計邏輯猖毫,使用情景分析的方...
    詭異的葉子閱讀 613評論 0 5
  • Git命令大全 git config 配置 Git 的相關(guān)參數(shù)台谍。 Git 一共有3個配置文件: 1. 倉庫級的配置...
    笑葉林閱讀 142,880評論 11 141
  • 2016年,經(jīng)歷的事不多吁断,后半年只有一件——考研趁蕊。 期間搖擺不定,但從沒質(zhì)疑過自己的方向仔役。 也不知道該說些什么掷伙,這...
    格格曙閱讀 201評論 0 0
  • #幸福是需要修出來的~每天進(jìn)步1%~幸福實修13班~22唐潔# 20180102(36/60) 【幸福三朵玫瑰】 ...
    你謝謝閱讀 153評論 0 2
  • 昨天一位兩個孩子的爸爸很困惑的問我兩個問題任柜,1.他說他的兩個孩子很貪玩,靜不下心來學(xué)習(xí)沛厨;2宙地、他在家里的時候和不...
    47c5277e96f6閱讀 160評論 0 0