策略模式(新手推薦)

設計模式是個神奇的東西,用得好的話可以讓你的代碼結構清晰簡潔矩桂,用得不好則會讓結構更加復雜難懂昔榴,包括使用過度。下面我打算分好幾部分介紹下自己所理解的設計模式捌省。

最近在看一本關于設計模式的書《深入淺出設計模式》苫纤,覺得書中講的很生動形象。我打算用自己的理解結合書中的例子纲缓,給大家簡單解釋一下卷拘,適合和我一樣的新手,同時歡迎大神批評指正祝高。首先從策略模式開始栗弟。下面大家來看一個例子:


現(xiàn)在有抽象父類People,里面有eat()和sleep()等共有的方法以及抽象方法show()工闺。下面有三個子類man乍赫,woman以及child,在子類中我們實現(xiàn)對應的show()方法。似乎并沒有什么問題陆蟆,大家都很好雷厂。具體代碼如下:

?People

public abstract class People {

public void eat(){

System.out.println("all people eat");

}

public void sleep(){

System.out.println("all people sleep");

}

public abstract void show();

}

?Man

public class Man extends People{

@Override

public void show() {

System.out.println("I have short hair");

}

}

?Woman

public class Woman extends People {

@Override

public void show() {

System.out.println("I have long hair");

}

}

Child

public class Child extends People {

@Override

public void show() {

System.out.println("I have less hair");

}

}

分析以上代碼,我們將公有部分(eat和sleep)在抽象類People實現(xiàn)叠殷,show在具體子類中實現(xiàn)改鲫。(不要說我吃米飯,嬰兒吃奶嘴林束,eat應該不同的像棘,大家安靜安靜別吵,現(xiàn)在不是糾結這個的時候)只能說我這個例子舉的不太恰當壶冒,因為實際需求中總有一部分是固定不變的缕题,我們這一步的任務就是將固定不變的抽取出來父類中實現(xiàn)而已。

這個地方有個很重要的思想胖腾,就是面對一個系統(tǒng)或者說一個模塊烟零,我們將固定不變的部分與經常變化的部分區(qū)分開來,分別對待胸嘁,小心產品經理瓶摆。

假設我現(xiàn)在需求要變,要所有的人都有move()方法性宏。你會怎么做群井?你肯定會說我們都是面向對象編程,很簡單啊毫胜,直接在People中增加move()方法并實現(xiàn)书斜,這種上課時老師一直講的東西诬辈,繼承。


**可是你想過沒有荐吉,這樣做會不會有什么問題焙糟?**


child嬰兒是不會移動的(不要糾結說嬰兒會爬之類的,我眼睛會干)样屠。這時候你會發(fā)現(xiàn)如果我們在父類中實現(xiàn)穿撮,那么將影響整個子類,這對于子類較多的類來說痪欲,是災難性的悦穿。你肯定就會說,我們在People中設計一個抽象方法move()业踢,然后在子類中實現(xiàn)不可以嗎栗柒?

當然可以,代碼如下:

?People

public abstract class People {

public void eat(){

System.out.println("all people eat");

}

public void sleep(){

System.out.println("all people sleep");

}

public abstract void show();

public abstract void move();

}

Man

public class Man extends People{

@Override

public void show() {

System.out.println("I have short hair");

}

@Override

public void move() {

System.out.println("on foot");

}

}

Woman

public class Woman extends People {

@Override

public void show() {

System.out.println("I have long hair");

}

@Override

public void move() {

System.out.println("on foot");

}

}

Child

public class Child extends People {

@Override

public void show() {

System.out.println("I have less hair");

}

@Override

public void move() {

}

}

好了知举,實現(xiàn)完成瞬沦。在child類中,move()中我們什么也不做」臀現(xiàn)在需求來了逛钻,我們有一類人懶人。雖然是個大老爺們锰提,但是我不想動绣的,我被床封印了。你會怎么做欲账?重新創(chuàng)建一個LazyMan類繼承People,然后實現(xiàn)move(),在move中什么也不做芭概?

你會說怎么不可以赛不??罢洲?

child和LazyMan中代碼代碼重復踢故,做到代碼重用了嗎?什么惹苗,實現(xiàn)為空也叫代碼重復殿较?


住口。在Man和Woman中move不是已經代碼重復了嗎桩蓉?還敢嘴硬淋纲。少年還有什么可說的?院究?

你會說洽瞬,看來不行啊本涕,我們必須求助于其他辦法了。對的伙窃,我們試試其他辦法菩颖。

能不能用接口?然后創(chuàng)建多個接口的子類分別實現(xiàn)为障?


具體實現(xiàn)如下:

?IMoveBehavior

public interface IMoveBehavior {

public void move();

}

?MoveWithFoot

public class MoveWithFoot implements IMoveBehavior {

@Override

public void move() {

System.out.println("on foot");

}

}

MoveNothing

public class MoveNothing implements IMoveBehavior{

@Override

public void move() {

System.out.println("move? no");

}

}

?來看看我們的People

public abstract class People {

IMoveBehavior moveBehavior;

public void eat(){

System.out.println("all people eat");

}

public void sleep(){

System.out.println("all people sleep");

}

public abstract void show();

public void moveBehave(){

moveBehavior.move();

}

}

我們在創(chuàng)建IMoveBehavior對象的時候需要知道IMoveBehavior具體指向的是什么晦闰,所以我們在People子類的構造函數(shù)中來指定。代碼如下:

Man

public class Man extends People implements IMoveBehavior{

public Man(IMoveBehavior moveBehavior){

this.moveBehavior = moveBehavior;

}

@Override

public void show() {

System.out.println("I have short hair");

}

@Override

public void move() {

System.out.println("on foot");

}

}

Woman和Child類似鳍怨,不貼了呻右。我們寫個測試類StrategyTest,看我們的代碼復用是否成功京景?

StrategyTest

public class StrategyTest {

public static void main(String[] args) {

Man niceMan = new Man(new MoveNothing());

niceMan.moveBehave();

}

}

運行結果如下:


如果是勤勞的人窿冯,那就 Man niceMan = new Man(new MoveWithFoot());

**問題解決,那還有沒有什么不妥的地方呢确徙?**

我們moveBehavior是在創(chuàng)建的時候進行綁定的醒串,如果我想動態(tài)地更改moveBehavior呢?是不是就傻眼了鄙皇?

于是我們有個接下來的方法:

People

public abstract class People {

IMoveBehavior moveBehavior;

public void setMoveBehavior(IMoveBehavior moveBehavior){

this.moveBehavior = moveBehavior;

}

public void eat(){

System.out.println("all people eat");

}

public void sleep(){

System.out.println("all people sleep");

}

public abstract void show();

public void moveBehave(){

moveBehavior.move();

}

}

其他類不變芜赌。我們將moveBehavior的設置方法暴露出去,可以進行動態(tài)設定伴逸。來驗證一下:

public class StrategyTest {

public static void main(String[] args) {

Man niceMan = new Man();

//給我走

niceMan.setMoveBehavior(new MoveWithFoot());

niceMan.moveBehave();

//不許動

niceMan.setMoveBehavior(new MoveNothing());

niceMan.moveBehave();

}

}

驗證結果如下:


幾經波折缠沈,終于搞好了。這就是策略模式错蝴,下面我們來看下較為正式的定義(嚴肅點洲愤,不許笑)。

策略模式:

定義了算法族顷锰,分別封裝起來柬赐,讓它們之間可以互相替換, 此模式讓算法的變化獨立于使用算法的客戶官紫。

最后說一個重要的點:我們之前那種做法都是通過繼承肛宋,面向實現(xiàn)做的,雖然可以得到要求束世,但是代碼復用性不高酝陈,如果子類多,那將是災難毁涉。我們要面向接口編程沉帮。

原則:少用繼承,多用組合。

拓展:

1.假設需求又變了遇西,需要給所有人加上wear(穿衣的方法)馅精,但是每種人的穿衣風格不同。男的穿西裝粱檀,女的穿裙子洲敢,小孩穿肚兜,甚至超人內褲外穿茄蚯。好解決嗎压彭?

2.需求又變了,要求move增加騎自行實現(xiàn)渗常。創(chuàng)造出喜歡騎自行車穿裙子的女生壮不,好解決嗎?嘿嘿嘿

最后有必要說一下皱碘,我文中出現(xiàn)猥瑣的語句只是為了提起大家的興趣询一,給大家將知識留下深刻的印象,我本人很正直癌椿,不信看我眼睛說話健蕊。

大家下期見,拜拜踢俄!

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
  • 序言:七十年代末缩功,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子都办,更是在濱河造成了極大的恐慌嫡锌,老刑警劉巖,帶你破解...
    沈念sama閱讀 218,858評論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件琳钉,死亡現(xiàn)場離奇詭異势木,居然都是意外死亡,警方通過查閱死者的電腦和手機歌懒,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,372評論 3 395
  • 文/潘曉璐 我一進店門跟压,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人歼培,你說我怎么就攤上這事∪兹” “怎么了躲庄?”我有些...
    開封第一講書人閱讀 165,282評論 0 356
  • 文/不壞的土叔 我叫張陵,是天一觀的道長钾虐。 經常有香客問我噪窘,道長,這世上最難降的妖魔是什么效扫? 我笑而不...
    開封第一講書人閱讀 58,842評論 1 295
  • 正文 為了忘掉前任倔监,我火速辦了婚禮直砂,結果婚禮上,老公的妹妹穿的比我還像新娘浩习。我一直安慰自己静暂,他們只是感情好,可當我...
    茶點故事閱讀 67,857評論 6 392
  • 文/花漫 我一把揭開白布谱秽。 她就那樣靜靜地躺著洽蛀,像睡著了一般。 火紅的嫁衣襯著肌膚如雪疟赊。 梳的紋絲不亂的頭發(fā)上郊供,一...
    開封第一講書人閱讀 51,679評論 1 305
  • 那天,我揣著相機與錄音近哟,去河邊找鬼驮审。 笑死,一個胖子當著我的面吹牛吉执,可吹牛的內容都是我干的疯淫。 我是一名探鬼主播,決...
    沈念sama閱讀 40,406評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼鼠证,長吁一口氣:“原來是場噩夢啊……” “哼峡竣!你這毒婦竟也來了?” 一聲冷哼從身側響起量九,我...
    開封第一講書人閱讀 39,311評論 0 276
  • 序言:老撾萬榮一對情侶失蹤适掰,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后荠列,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體类浪,經...
    沈念sama閱讀 45,767評論 1 315
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 37,945評論 3 336
  • 正文 我和宋清朗相戀三年肌似,在試婚紗的時候發(fā)現(xiàn)自己被綠了费就。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 40,090評論 1 350
  • 序言:一個原本活蹦亂跳的男人離奇死亡川队,死狀恐怖力细,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情固额,我是刑警寧澤眠蚂,帶...
    沈念sama閱讀 35,785評論 5 346
  • 正文 年R本政府宣布,位于F島的核電站斗躏,受9級特大地震影響逝慧,放射性物質發(fā)生泄漏。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,420評論 3 331
  • 文/蒙蒙 一笛臣、第九天 我趴在偏房一處隱蔽的房頂上張望云稚。 院中可真熱鬧,春花似錦沈堡、人聲如沸静陈。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,988評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽窿给。三九已至,卻和暖如春率拒,著一層夾襖步出監(jiān)牢的瞬間崩泡,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,101評論 1 271
  • 我被黑心中介騙來泰國打工猬膨, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留角撞,地道東北人。 一個月前我還...
    沈念sama閱讀 48,298評論 3 372
  • 正文 我出身青樓勃痴,卻偏偏與公主長得像谒所,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子沛申,可洞房花燭夜當晚...
    茶點故事閱讀 45,033評論 2 355

推薦閱讀更多精彩內容

  • 1. Java基礎部分 基礎部分的順序:基本語法劣领,類相關的語法,內部類的語法铁材,繼承相關的語法尖淘,異常的語法,線程的語...
    子非魚_t_閱讀 31,639評論 18 399
  • Spring Cloud為開發(fā)人員提供了快速構建分布式系統(tǒng)中一些常見模式的工具(例如配置管理著觉,服務發(fā)現(xiàn)村生,斷路器,智...
    卡卡羅2017閱讀 134,659評論 18 139
  • 據說饼丘,馬云是個好奇心超強的人趁桃,喜歡胡侃,也愛聽別人侃肄鸽。他曾經在湖畔大學說卫病,保持好奇心是很重要的,要有反思之心典徘,企業(yè)...
    snailwww閱讀 192評論 0 1
  • 先推薦一些編譯原理的材料: mooc上斯坦福的compilers課程 《形式語言與自動機導論》(An Introd...
    doyoubi閱讀 2,555評論 0 2
  • 都說基本功扎實忽肛,做什么都快。 今天要說的一個基本功烂斋,幾乎是所有人都知道的,只是沒有意識到。 那就是:仔細汛骂。 為什么...
    米米心臻閱讀 251評論 1 7