深入淺出策略模式

深入淺出設(shè)計(jì)模式(1)-策略模式

講義要解決問題

  • 什么是設(shè)計(jì)模式?
  • 為什么23種設(shè)計(jì)模式中沒有MVC模式
  • 一些OO設(shè)計(jì)原則與使用
  • 策略模式

什么設(shè)計(jì)模式佃迄?

設(shè)計(jì)模式并不直接用來完成代碼的編寫,而是描述在各種不同情況下夺饲,要怎么解決問題的一種方案装盯。面向?qū)ο?/a>設(shè)計(jì)模式通常以類別對象來描述其中的關(guān)系和相互作用,但不涉及用來完成應(yīng)用程序的特定類別或?qū)ο笏耪馈TO(shè)計(jì)模式能使不穩(wěn)定依賴于相對穩(wěn)定养泡、具體依賴于相對抽象,避免會引起麻煩的緊耦合奈应,以增強(qiáng)軟件設(shè)計(jì)面對并適應(yīng)變化的能力澜掩。

所以簡單來說設(shè)計(jì)模式就是一個(gè)軟件設(shè)計(jì)的藍(lán)圖,而我們就是藍(lán)圖的制作者杖挣,程序猿肩榕。

那就是為什么做設(shè)計(jì),作為搬磚的程序猿惩妇,總要手里有點(diǎn)貨株汉,為什么看別人的代碼總是很舒服,為什么再改產(chǎn)品經(jīng)理的需求的時(shí)候總是那么痛苦甚至修改一點(diǎn)要牽動全身歌殃?這些問題乔妈,完全可以用設(shè)計(jì)模式來提供大部分解決方案。

為什么23種模式中并沒有MVC模式

GoF (Gang of Four氓皱,四人組路召, 《Design Patterns: Elements of Reusable Object-Oriented Software》/《設(shè)計(jì)模式》一書的作者:Erich Gamma钞楼、Richard Helm瘤载、Ralph Johnson、John Vlissides)并沒有把MVC提及為一種設(shè)計(jì)模式,而是把它當(dāng)做“一組用于構(gòu)建用戶界面的類集合”澡绩。在他們看來,它其實(shí)是其它三個(gè)經(jīng)典的設(shè)計(jì)模式的演變:觀察者模式(Observer)(Pub/Sub), 策略模式(Strategy)和組合模式(Composite)叛氨。

作者:lorio鏈接:https://www.zhihu.com/question/27738109/answer/100241918來源:知乎著作權(quán)歸作者所有达址。商業(yè)轉(zhuǎn)載請聯(lián)系作者獲得授權(quán),非商業(yè)轉(zhuǎn)載請注明出處早敬。

其實(shí)MVC 也是模式忌傻,但是是多種設(shè)計(jì)模式的演變,我們實(shí)際編寫的時(shí)候可以看到有很多MVC框架搞监,是對MVC模式的一種藍(lán)圖實(shí)踐水孩。

一些OO設(shè)計(jì)原則與使用

從OO來講可能更令人容易理解,下面是一套完整的產(chǎn)品編寫代碼邏輯琐驴,可能有點(diǎn)長俘种,但是一定會發(fā)現(xiàn)開始我們寫程序的時(shí)候就是這么干的 。

下面我們用Head First 設(shè)計(jì)模式中的一篇栗子在解釋:

這是一個(gè)模擬鴨子游戲:游戲中會出現(xiàn)各種鴨子绝淡,一邊游泳宙刘,一邊叫。

這個(gè)應(yīng)用用的是OO技術(shù)有一個(gè)鴨子超類(superclass)牢酵,并讓各種鴨子繼承此類悬包。

public abstract class Duck {
    public Duck() {}
  
    abstract void display();
  
    public void quack() {}

    public void swim() {}
}

public class MallardDuck extends Duck {
    //外觀是綠頭鴨
    public MallardDuck() {}

    public void display() {}
}

public class RedHeadDuck extends Duck {
 
    public RedHeadDuck() {}
 
    public void display() {}
}

但是Nathan組織了異常頭腦風(fēng)暴,然后決定要讓鴨子們會飛馍乙,我們怎么做布近?程序猿們說 很簡單于是

public class Duck {
    public Duck() {}
  
    public void quack() {}

    public void swim() {}
  
    public void fly(){}
}

所有的鴨子都會飛了,但是……丝格,他們的游戲里面有一只橡皮鴨撑瞧,Nathan攤手表示,橡皮鴨是為什么會飛的铁追。季蚂。。琅束。這時(shí)候你會怎么辦扭屁?

OO來說我們繼承覆蓋就好了

public class RubberDuck extends Duck {
  public void display() {};
  
  public void quack(){};
    
  public void fly(){
    //什么都不做
  }
}

但是如果以后加入鐵鴨子怎么辦?不會飛也不會叫

那下面我們用OO中的接口如何涩禀?也就是說把fly()quack()寫成接口料滥,下面的鴨子進(jìn)行繼承。會有什么問題呢艾船?

如果是你你會怎么辦葵腹?

采用良好的00軟件設(shè)計(jì)原則:

  1. 原則一:

找出應(yīng)用中可能需要變化的地方高每,把它們獨(dú)立出來,不要和那些不需要變化的代碼混在一起践宴,這時(shí)候你就可以很好的修改或者擴(kuò)展這部分鲸匿,而不影響不需要變化的其他部分。

到底哪一些是Duck類變得以及不變的阻肩?

  • fly()與quack()會隨著不同而改變
  • 你沒有辦法開始就知道带欢,但是可以再改需求的時(shí)候慢慢修改提煉
  1. 原則二:

針對接口編程,而不是針對實(shí)現(xiàn)編程

這個(gè)對于我們OO來說很需要了解烤惊,我目前總是針對實(shí)現(xiàn)編程而不是接口編程乔煞。在栗子中怎么實(shí)現(xiàn)呢?那就是鴨子的行為將被放在分開的類中柒室,專門提供某行為的接口的實(shí)現(xiàn)渡贾,鴨子的類就不需要知道行為的實(shí)現(xiàn)細(xì)節(jié)

舉個(gè)栗子:

public interface FlyBehavior {
    public void fly();
}

public class FlyWithWings implements FlyBehavior {
    public void fly() {
        System.out.println("I'm flying!!");
    }
}

public class FlyNoWay implements FlyBehavior {
    public void fly() {
        System.out.println("I can't fly");
    }
}

public interface QuackBehavior {
    public void quack();
}

public class Quack implements QuackBehavior {
    public void quack() {
      //呱呱叫
        System.out.println("Quack");
    }
}

public class Squeak implements QuackBehavior {
    public void quack() {
      //橡皮鴨子吱吱叫
        System.out.println("Squeak");
    }
}

public class MuteQuack implements QuackBehavior {
    public void quack() {
      //什么都不做,我不會叫
        System.out.println("<< Silence >>");
    }
}

那這些有什么好處雄右?對了行為單獨(dú)一個(gè)類空骚,實(shí)現(xiàn)了解耦,這些行為和鴨子無關(guān)了不脯,以后Nathan要什么的鴨子府怯,我們程序猿都可以給他了。

這時(shí)候有個(gè)問題防楷,我們要在什么時(shí)候分離封裝呢?

解耦很清晰则涯,可是我們要怎么整合起來呢复局?讓鴨子更像一個(gè)鴨子,先要在duck加兩個(gè)實(shí)體變量

public abstract class Duck {
    FlyBehavior flyBehavior;
    QuackBehavior quackBehavior;
  
    abstract void display();

    public void performFly() {
        flyBehavior.fly();
    }

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

    public void swim() {
        System.out.println("All ducks float, even decoys!");
    }
}


public class MallardDuck extends Duck {

    public MallardDuck() {
      //在構(gòu)造綠頭鴨的時(shí)候裝配上叫和飛的行為粟判,這個(gè)綠頭鴨就真的會飛和叫了
        quackBehavior = new Quack();
        flyBehavior = new FlyWithWings();
    }

    public void display() {
        System.out.println("I'm a real Mallard duck");
    }
}

編寫好了亿昏,如何測試呢?

public class MiniDuckSimulator {

    public static void main(String[] args) {
 
        MallardDuck mallard = new MallardDuck();
        RubberDuck  rubberDuckie = new RubberDuck();
        DecoyDuck   decoy = new DecoyDuck();
 
        mallard.performQuack();
        rubberDuckie.performQuack();
        decoy.performQuack();
    }
}

講了這么多档礁,我們從新的梳理一下角钩,到底整體的一個(gè)架構(gòu)是什么樣子的,這時(shí)候請不要把鴨子的行為說成行為呻澜,我們把行為想象成一族算法递礼,這樣行為是不是就可以遷移到很多地方了,下面我來畫UML圖羹幸,請看黑板

  1. 原則三

多用組合脊髓,少用繼承。

上面我們看了組合建立系統(tǒng)的具有很大的彈性栅受,可以把算法族封裝成類将硝,還可以隨意組合恭朗,只要符合正確的接口。

以后要做什么捕捉鴨子的鴨鳴器繼承一個(gè)算法就可以很快實(shí)現(xiàn)依疼。

上述其實(shí)講解OO原則的時(shí)候你已經(jīng)學(xué)會了策略模式痰腮。

策略模式

定義了算法族,分別封裝起來律罢,讓他們之間可以互相替換膀值,此模式讓算法的變化獨(dú)立與使用算法的客戶

最后一個(gè)問題:我如何使用設(shè)計(jì)模式

你再大腦中裝入了關(guān)于模式的知識,以后在新的設(shè)計(jì)中弟翘,就可以重做之前在你腦子中的舊代碼虫腋!

算法像是”單兵作戰(zhàn)和武器裝備“,設(shè)計(jì)模式像是”仗列的陣型“稀余。算法用來解決具體問題悦冀,設(shè)計(jì)模式用來合理的把算法隔離到各個(gè)正確的地方去。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末睛琳,一起剝皮案震驚了整個(gè)濱河市盒蟆,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌师骗,老刑警劉巖历等,帶你破解...
    沈念sama閱讀 222,729評論 6 517
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異辟癌,居然都是意外死亡寒屯,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 95,226評論 3 399
  • 文/潘曉璐 我一進(jìn)店門黍少,熙熙樓的掌柜王于貴愁眉苦臉地迎上來寡夹,“玉大人,你說我怎么就攤上這事厂置∑刑停” “怎么了?”我有些...
    開封第一講書人閱讀 169,461評論 0 362
  • 文/不壞的土叔 我叫張陵昵济,是天一觀的道長智绸。 經(jīng)常有香客問我,道長访忿,這世上最難降的妖魔是什么瞧栗? 我笑而不...
    開封第一講書人閱讀 60,135評論 1 300
  • 正文 為了忘掉前任,我火速辦了婚禮醉顽,結(jié)果婚禮上沼溜,老公的妹妹穿的比我還像新娘。我一直安慰自己游添,他們只是感情好系草,可當(dāng)我...
    茶點(diǎn)故事閱讀 69,130評論 6 398
  • 文/花漫 我一把揭開白布通熄。 她就那樣靜靜地躺著,像睡著了一般找都。 火紅的嫁衣襯著肌膚如雪唇辨。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 52,736評論 1 312
  • 那天能耻,我揣著相機(jī)與錄音赏枚,去河邊找鬼。 笑死晓猛,一個(gè)胖子當(dāng)著我的面吹牛饿幅,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播戒职,決...
    沈念sama閱讀 41,179評論 3 422
  • 文/蒼蘭香墨 我猛地睜開眼栗恩,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了洪燥?” 一聲冷哼從身側(cè)響起磕秤,我...
    開封第一講書人閱讀 40,124評論 0 277
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎捧韵,沒想到半個(gè)月后市咆,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 46,657評論 1 320
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡再来,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,723評論 3 342
  • 正文 我和宋清朗相戀三年蒙兰,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片芒篷。...
    茶點(diǎn)故事閱讀 40,872評論 1 353
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡癞己,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出梭伐,到底是詐尸還是另有隱情,我是刑警寧澤仰担,帶...
    沈念sama閱讀 36,533評論 5 351
  • 正文 年R本政府宣布糊识,位于F島的核電站,受9級特大地震影響摔蓝,放射性物質(zhì)發(fā)生泄漏赂苗。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 42,213評論 3 336
  • 文/蒙蒙 一贮尉、第九天 我趴在偏房一處隱蔽的房頂上張望拌滋。 院中可真熱鬧,春花似錦猜谚、人聲如沸败砂。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,700評論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽昌犹。三九已至坚芜,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間斜姥,已是汗流浹背鸿竖。 一陣腳步聲響...
    開封第一講書人閱讀 33,819評論 1 274
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留铸敏,地道東北人缚忧。 一個(gè)月前我還...
    沈念sama閱讀 49,304評論 3 379
  • 正文 我出身青樓,卻偏偏與公主長得像杈笔,于是被迫代替她去往敵國和親闪水。 傳聞我的和親對象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,876評論 2 361

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

  • Android 自定義View的各種姿勢1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 172,328評論 25 707
  • 1 場景問題# 1.1 報(bào)價(jià)管理## 向客戶報(bào)價(jià)桩撮,對于銷售部門的人來講敦第,這是一個(gè)非常重大、非常復(fù)雜的問題店量,對不同的...
    七寸知架構(gòu)閱讀 5,096評論 9 62
  • 兒子十四了芜果,進(jìn)入青春期的第一年。
    吉人天相SP閱讀 147評論 0 0
  • 隨著寶寶的不斷成長,到了寶寶三個(gè)月的時(shí)候旱爆,細(xì)心的媽媽有一天突然發(fā)現(xiàn)寶寶不斷在吐泡泡舀射,有人告訴媽媽說這是肺炎的癥狀,...
    淘嘉園閱讀 500評論 0 0
  • 偷偷告訴你們怀伦,原來我們的班主任也是一個(gè)小拖拉脆烟。沒辦法,每個(gè)人都有惰性啊房待。 六一兒童節(jié)邢羔,兒童的節(jié)日。我想把節(jié)日還給兒...
    小茜茜公主閱讀 359評論 0 1