摘要:引言要分析設(shè)計(jì)模式中的策略模式,我們可以以希伯來圣經(jīng)中的一個(gè)故事為例。策略模式原理及益處這個(gè)策略依然有一個(gè)父類相當(dāng)于一個(gè)模板,所有的人類子類都繼承這個(gè)父類根據(jù)這個(gè)模板來創(chuàng)建。
引言
要分析設(shè)計(jì)模式中的“策略模式”,我們可以以《希伯來圣經(jīng)》中的一個(gè)故事為例。
《希伯來圣經(jīng)》中有這樣一個(gè)故事,說的是人類產(chǎn)生不同語言的起源。在這個(gè)故事中,一群只說一種語言的人在“大洪水”之后從東方來到了示拿地區(qū),并決定在這修建一座城市和一座“能夠通天的”高塔;上帝見此情形就把他們的語言打亂,讓他們?cè)僖膊荒苊靼讓?duì)方的意思,并把他們分散到了世界各地。
這里我們可以將God視作一個(gè)程序員。
在他的設(shè)計(jì)中,所有的人類(Human),雖然有很多個(gè)個(gè)體,但一開始都是一樣的,說的是一樣的語言。
所以我們可以將Human類作為父類,然后所有的人類個(gè)體對(duì)象都繼承這個(gè)Human父類。父類中有一個(gè)speak()方法,所有繼承Human類的子類都將繼承這個(gè)方法,于是都擁有了用語言交流的能力。
//Human父類 public class Human { public void speak(){ System.out.println("只要是人類的子類都speak the same language"); } }
可以有很多的人類種類繼承這個(gè)Human父類,比如來自東方的的人:
public class PeopleFromEast extends { //PeopleFromEast繼承了Human, //所以也就繼承了Human父類中的speak()方法 //所以PeopleFromEast類中甚至都不需要寫任何方法 }
在demo測試中,我們可以看到,PeopleFromEast類的對(duì)象,可以調(diào)用從父類繼承來的speak()方法:
public class RunDemo { public static void main (String[] args){ //創(chuàng)建一個(gè)PeopleFromEast對(duì)象 PeopleFromEast peopleFromEast = new PeopleFromEast(); //讓這個(gè)對(duì)象調(diào)用從父類繼承來的方法speak() peopleFromEast.speak(); } }
根據(jù)God最初的設(shè)想,這樣的設(shè)計(jì)是沒有問題的。
“土方法”的缺陷可是后來由于語言一致,人類同心協(xié)力修建巴比塔,(程序猿)God感到受到了威脅。于是決定做出改變:讓來自不同地方的人speak不同的language——比如PeopleFromEast說EastLanguage,PeopleFromWest說WestLanguage,等等。
God要實(shí)現(xiàn)這樣的改變,最直觀的方法自然是讓每個(gè)繼承Human父類的人類子類重寫父類的speak()方法。
//新的PeopleFromEast類 //這一次PeopleFromEast重寫了speak()方法 public class PeopleFromEast extends Human { @Override public void speak() { System.out.println("PeopleFromEast從今以后只能speak EastLanguage"); } }
demo的運(yùn)行結(jié)果:
如果人類的子類種類不多,那么(程序猿God)還可以每次都重寫Human子類的speak()方法??墒侨绻祟惖淖宇愑泻芏喾N呢?又或者不止speak()方法有這種情況呢?比如,也許God以后希望讓每種人類子類的行走方式都不一樣。那是不是應(yīng)該在Human父類中加入一個(gè)walk()方法,然后讓每個(gè)子類都重寫呢?
也就是說,如果人類子類的“規(guī)格”常常改變,每當(dāng)有新的人類子類出現(xiàn),(程序猿)God都要被迫檢查并可能需要覆蓋speak()和walk(),這絕對(duì)是God所不愿意看見的。
策略模式原理及益處這個(gè)策略依然有一個(gè)Human父類(相當(dāng)于一個(gè)模板),所有的人類子類都繼承這個(gè)父類(根據(jù)這個(gè)模板來創(chuàng)建)。
所不同的是,這次God決定在每個(gè)人類的子類中都附上自己的一份意識(shí)。讓這份意識(shí)來控制這個(gè)子類應(yīng)該說的語言種類。為了方便敘述,我們可以將God的這一意識(shí)稱為LanguageController。
然后,God為人類的子類可以說的Language種類提供了一個(gè)選擇范圍。
比如,中國人(ChineseMan--因?yàn)镃hinese既可以表示“中文”又可以表示“中國人”,為了區(qū)分,我們稱“中國人”為"ChineseMan")說中文(Chinese),美國人(American)就說英文(English)。
這樣一來,在每個(gè)人類子類創(chuàng)建時(shí),God附在其上的意識(shí)LanguageController將發(fā)揮作用,然后按照God的意愿,從language的可選范圍中選擇一種語言來指定給該人類子類。
這一策略在程序設(shè)計(jì)中可以這樣實(shí)現(xiàn):
創(chuàng)建一個(gè)Human父類:
public class Human { //LanguageController是接口類型 //languageController作為Human類的field, //代表God將自己的意識(shí)附在人類父類之上, //也就代表God的意識(shí)將附在所有的人類個(gè)體之上 LanguageController languageController ; //根據(jù)God的設(shè)計(jì),人類的模板中只需要作出規(guī)定:人會(huì)說某種語言 //而不需要作出具體的安排 public void performSpeaking (){ //人說話的時(shí)候,還得上帝的意識(shí)起作用, //決定這個(gè)“具體的人”該說何種語言 languageController.speak(); } }
創(chuàng)建LanguageController接口:
//創(chuàng)造God的意識(shí),也就是LanguageController: public interface LanguageController { //接口中只定義了一個(gè)speak()方法 public void speak(); }
現(xiàn)在God要?jiǎng)?chuàng)造中國人和美國人:
ChineseMan類:
public class ChineseMan extends Human { //中國人對(duì)象的構(gòu)造器 ChineseMan() { //構(gòu)造ChineseMan對(duì)象時(shí),God的意識(shí)發(fā)揮作用 //languageController是從Human父類繼承來的 //根據(jù)God的安排,要?jiǎng)?chuàng)建ChineseMan對(duì)象,就應(yīng)該告訴languageController現(xiàn)在要?jiǎng)?chuàng)造的這個(gè)對(duì)象說中文 languageController = new speakChinese(); //在這里,由于多態(tài)的緣故,表現(xiàn)為具體子類--也就是speakChinese對(duì)象 skinColorController = new ColorIsLikeAsian(); } }
American類:
public class American extends Human { //American的構(gòu)造器 public American (){ languageController = new SpeakEnglish(); } }
那么這個(gè)speakChinese類和speakEnglish類有什么玄機(jī)呢?
speakChinese類:
//speakChinese類實(shí)現(xiàn)了LanguageController接口 public class speakChinese implements LanguageController{ //實(shí)現(xiàn)LanguageController接口中規(guī)定的speak()方法 @Override public void speak() { System.out.println("我說中文!"); } }
speakChinese類可能不太好理解,因?yàn)閟peak Chinese(說中文)更多算是一種行為(action),這里卻定義為類。其實(shí)只需要換一種思維,把speakChinese類視作一種標(biāo)簽,把這個(gè)標(biāo)簽賦給God的意識(shí)(languageContronller),也就實(shí)現(xiàn)了根據(jù)不同的human子類來確定不同的語言。
speakEnglish類:
//SpeakEnglish類實(shí)現(xiàn)了LanguageController接口 public class SpeakEnglish implements LanguageController { @Override public void speak() { System.out.println("I speak English!"); } }
下面運(yùn)行一個(gè)demo--StrategyModeDemo.java:
public class StrategyModeDemo { public static void main(String[] args){ //新建一個(gè)ChineseMan對(duì)象 Human chineseMan = new ChineseMan(); //ChineseMan說的語言: chineseMan.performSpeaking(); //American對(duì)象: Human american = new American(); //American說的語言: american.performSpeaking(); } }
StrategyModeDemo.java運(yùn)行結(jié)果:
執(zhí)行邏輯圖示而整個(gè)執(zhí)行流程的邏輯則如圖所示:
更上一層樓當(dāng)然,以上所有的Human子類在被創(chuàng)建時(shí),他們說什么話就已經(jīng)注定了。
這是因?yàn)樗麄兊腉od的意識(shí)起作用的環(huán)節(jié)在他們的構(gòu)造器中。
那么God有沒有辦法讓已經(jīng)被造出來的ChineseMan對(duì)象改說English呢?
答案是肯定的!
我們只需要在Human.java中加入一個(gè)修改語言的方法即可:
public class Human { LanguageController languageController ; SkinColorController skinColorController; //控制Human的子類說的語言,比如中國人說中文 public void performSpeaking (){ languageController.speak(); } //隨時(shí)改變能說的語言 public void setLanguage (LanguageController languageController){ languageController.speak(); } }
再次運(yùn)行StrategyModeDemo.java:
public class StrategyModeDemo { public static void main(String[] args){ //新建一個(gè)ChineseMan對(duì)象 Human chineseMan = new ChineseMan(); //ChineseMan說的語言: chineseMan.performSpeaking(); System.out.println("God決定讓ChineseMan也說英文"); chineseMan.setLanguage(new SpeakEnglish()); } }
個(gè)人淺見,如有不足,歡迎批評(píng)指正:)
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/74616.html
摘要:可以使用其他模式來修正這個(gè)缺陷,如工廠方法模式代理模式或享元模式。我們的策略模式只是實(shí)現(xiàn)了策略的管理,但是沒有嚴(yán)格地定義適當(dāng)?shù)膱鼍笆褂眠m當(dāng)?shù)牟呗裕趯?shí)際項(xiàng)目中,一般通過工廠方法模式來實(shí)現(xiàn)策略類的聲明。源碼地址參考文獻(xiàn)設(shè)計(jì)模式之禪 定義 Define a family of algorithms,encapsulate each one,and make them interchange...
摘要:一定義定義維基百科策略模式作爲(wèi)一種軟件設(shè)計(jì)模式,指對(duì)象有某個(gè)行爲(wèi),但是在不同的場景中,該行爲(wèi)有不同的實(shí)現(xiàn)算法。二策略模式圖我們看看策略模式是有怎樣設(shè)計(jì)結(jié)構(gòu)的。如中創(chuàng)建線程池,線程池任務(wù)滿時(shí),對(duì)提交的任務(wù)做處理就使用了策略模式。以前完整的看過《大話設(shè)計(jì)模式》,雖然完整看過,也做過筆記,但現(xiàn)在依然很多已經(jīng)很模糊。這段時(shí)間趁著離職,有時(shí)間,打算重新過一遍,該篇將介紹策略模式。一、定義定義(維基百科...
摘要:一定義定義維基百科策略模式作爲(wèi)一種軟件設(shè)計(jì)模式,指對(duì)象有某個(gè)行爲(wèi),但是在不同的場景中,該行爲(wèi)有不同的實(shí)現(xiàn)算法。二策略模式圖我們看看策略模式是有怎樣設(shè)計(jì)結(jié)構(gòu)的。如中創(chuàng)建線程池,線程池任務(wù)滿時(shí),對(duì)提交的任務(wù)做處理就使用了策略模式。以前完整的看過《大話設(shè)計(jì)模式》,雖然完整看過,也做過筆記,但現(xiàn)在依然很多已經(jīng)很模糊。這段時(shí)間趁著離職,有時(shí)間,打算重新過一遍,該篇將介紹策略模式。一、定義定義(維基百科...
摘要:一定義定義維基百科策略模式作爲(wèi)一種軟件設(shè)計(jì)模式,指對(duì)象有某個(gè)行爲(wèi),但是在不同的場景中,該行爲(wèi)有不同的實(shí)現(xiàn)算法。二策略模式圖我們看看策略模式是有怎樣設(shè)計(jì)結(jié)構(gòu)的。如中創(chuàng)建線程池,線程池任務(wù)滿時(shí),對(duì)提交的任務(wù)做處理就使用了策略模式。以前完整的看過《大話設(shè)計(jì)模式》,雖然完整看過,也做過筆記,但現(xiàn)在依然很多已經(jīng)很模糊。這段時(shí)間趁著離職,有時(shí)間,打算重新過一遍,該篇將介紹策略模式。一、定義定義(維基百科...
摘要:孫臏心里一萬個(gè)草泥馬在奔騰,差點(diǎn)沒噎死自己滾一邊去,我們這盤跟他賽馬開始,策略模式上場。在設(shè)計(jì)模式之禪中的提出通過策略枚舉和反射機(jī)制對(duì)策略模式進(jìn)行改良,膜拜了但是要添加或淘汰策略,還是得去對(duì)枚舉進(jìn)行修改,也不符合開閉原則。 今天給大家說說田忌賽馬的故事。如有雷同,純屬巧合!話說在戰(zhàn)國時(shí)期,群雄割據(jù),硝煙四起,茶余飯后還是少不了娛樂活動(dòng)的,其中賽馬是最火爆的。一天,孫臏看到田忌像個(gè)死雞似...
閱讀 2688·2023-04-25 20:19
閱讀 1954·2021-11-24 09:38
閱讀 1639·2021-11-16 11:44
閱讀 4378·2021-09-02 15:40
閱讀 1361·2019-08-30 15:55
閱讀 2030·2019-08-30 15:52
閱讀 3770·2019-08-29 17:20
閱讀 2283·2019-08-29 13:48