研磨設(shè)計(jì)模式之 工廠方法模式_第1頁(yè)
研磨設(shè)計(jì)模式之 工廠方法模式_第2頁(yè)
研磨設(shè)計(jì)模式之 工廠方法模式_第3頁(yè)
研磨設(shè)計(jì)模式之 工廠方法模式_第4頁(yè)
研磨設(shè)計(jì)模式之 工廠方法模式_第5頁(yè)
已閱讀5頁(yè),還剩31頁(yè)未讀 繼續(xù)免費(fèi)閱讀

下載本文檔

版權(quán)說(shuō)明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)

文檔簡(jiǎn)介

1、研磨設(shè)計(jì)模式之 工廠方法模式-1    做Java一晃就十年了,最近手癢癢,也決定跟隨一下潮流,整個(gè)博客,寫點(diǎn)東西,就算對(duì)自己的知識(shí)進(jìn)行一個(gè)梳理和總結(jié),也跟朋友們交流交流,希望能堅(jiān)持下去。     先寫寫設(shè)計(jì)模式方面的內(nèi)容吧,就是GoF的23個(gè)模式,先從大家最熟悉的工廠方法模式開(kāi)始,這個(gè)最簡(jiǎn)單,明白的人多,看看是否能寫出點(diǎn)跟別人不一樣的東西,歡迎大家來(lái)熱烈討論,提出建議或意見(jiàn),并進(jìn)行批評(píng)指正,一概虛心接受,在此先謝過(guò)了!     另外,大家也可以說(shuō)說(shuō)最想看到哪個(gè)模式,那我就先寫它,呵呵,大家感興趣,我才會(huì)

2、有動(dòng)力寫下去!好了,言歸正傳,Now Go!工廠方法模式(Factory Method)1  場(chǎng)景問(wèn)題1.1  導(dǎo)出數(shù)據(jù)的應(yīng)用框架        考慮這樣一個(gè)實(shí)際應(yīng)用:實(shí)現(xiàn)一個(gè)導(dǎo)出數(shù)據(jù)的應(yīng)用框架,來(lái)讓客戶選擇數(shù)據(jù)的導(dǎo)出方式,并真正執(zhí)行數(shù)據(jù)導(dǎo)出。        在一些實(shí)際的企業(yè)應(yīng)用中,一個(gè)公司的系統(tǒng)往往分散在很多個(gè)不同的地方運(yùn)行,比如各個(gè)分公司或者是門市點(diǎn),公司沒(méi)有建立全公司專網(wǎng)的實(shí)力,但是又不愿意讓業(yè)務(wù)數(shù)據(jù)實(shí)時(shí)的在廣域網(wǎng)上傳遞,一個(gè)是考

3、慮數(shù)據(jù)安全的問(wèn)題,一個(gè)是運(yùn)行速度的問(wèn)題。        這種系統(tǒng)通常會(huì)有一個(gè)折中的方案,那就是各個(gè)分公司內(nèi)運(yùn)行系統(tǒng)的時(shí)候是獨(dú)立的,是在自己分公司的局域網(wǎng)內(nèi)運(yùn)行。然后在每天業(yè)務(wù)結(jié)束的時(shí)候,各個(gè)分公司會(huì)導(dǎo)出自己的業(yè)務(wù)數(shù)據(jù),然后把業(yè)務(wù)數(shù)據(jù)打包通過(guò)網(wǎng)絡(luò)傳送給總公司,或是專人把數(shù)據(jù)送到總公司,然后由總公司進(jìn)行數(shù)據(jù)導(dǎo)入和核算。        通常這種系統(tǒng),在導(dǎo)出數(shù)據(jù)上,會(huì)有一些約定的方式,比如導(dǎo)出成:文本格式、數(shù)據(jù)庫(kù)備份形式、Excel格式、Xml格式等等。 

4、;       現(xiàn)在就來(lái)考慮實(shí)現(xiàn)這樣一個(gè)應(yīng)用框架。在繼續(xù)之前,先來(lái)了解一些關(guān)于框架的知識(shí)。1.2  框架的基礎(chǔ)知識(shí)(1):框架是什么        簡(jiǎn)單點(diǎn)說(shuō):框架就是能完成一定功能的半成品軟件。        就其本質(zhì)而言,框架是一個(gè)軟件,而且是一個(gè)半成品的軟件。所謂半成品,就是還不能完全實(shí)現(xiàn)用戶需要的功能,框架只是實(shí)現(xiàn)用戶需要的功能的一部分,還需要進(jìn)一步加工,才能成為一個(gè)滿足用戶需要的

5、、完整的軟件。因此框架級(jí)的軟件,它的主要客戶是開(kāi)發(fā)人員,而不是最終用戶。        有些朋友會(huì)想,既然框架只是個(gè)半成品,那何必要去學(xué)習(xí)和使用框架呢?學(xué)習(xí)成本也不算小,那就是因?yàn)榭蚣苣芡瓿梢欢ǖ墓δ?,也就是這“框架已經(jīng)完成的一定的功能”在吸引著開(kāi)發(fā)人員,讓大家投入去學(xué)習(xí)和使用框架。(2):框架能干什么        能完成一定功能,加快應(yīng)用開(kāi)發(fā)進(jìn)度        由于框架完成了一定的功

6、能,而且通常是一些基礎(chǔ)的、有難度的、通用的功能,這就避免我們?cè)趹?yīng)用開(kāi)發(fā)的時(shí)候完全從頭開(kāi)始,而是在框架已有的功能之上繼續(xù)開(kāi)發(fā),也就是說(shuō)會(huì)復(fù)用框架的功能,從而加快應(yīng)用的開(kāi)發(fā)進(jìn)度。        給我們一個(gè)精良的程序架構(gòu)        框架定義了應(yīng)用的整體結(jié)構(gòu),包括類和對(duì)象的分割,各部分的主要責(zé)任,類和對(duì)象怎么協(xié)作,以及控制流程等等?,F(xiàn)在Java界大多數(shù)流行的框架,大都出自大師手筆,設(shè)計(jì)都很精良?;谶@樣的框架來(lái)開(kāi)發(fā),一般會(huì)遵循框架已經(jīng)規(guī)劃好的結(jié)構(gòu)來(lái)進(jìn)行開(kāi)發(fā),從

7、而讓我們開(kāi)發(fā)的應(yīng)用程序的結(jié)構(gòu)也相對(duì)變得精良了。(3):對(duì)框架的理解        基于框架來(lái)開(kāi)發(fā),事情還是那些事情,只是看誰(shuí)做的問(wèn)題        對(duì)于應(yīng)用程序和框架的關(guān)系,可以用一個(gè)圖來(lái)簡(jiǎn)單描述一下,如圖1所示:  圖1  應(yīng)用程序和框架的簡(jiǎn)單關(guān)系示意圖         如果沒(méi)有框架,那么客戶要求的所有功能都由開(kāi)發(fā)人員自己來(lái)開(kāi)發(fā),沒(méi)問(wèn)題,同樣可以

8、實(shí)現(xiàn)用戶要求的功能,只是開(kāi)發(fā)人員的工作多點(diǎn)。        如果有了框架,框架本身完成了一定的功能,那么框架已有的功能,開(kāi)發(fā)人員就可以不做了,開(kāi)發(fā)人員只需要完成框架沒(méi)有的功能,最后同樣是完成客戶要求的所有功能,但是開(kāi)發(fā)人員的工作就減少了。        也就是說(shuō),基于框架來(lái)開(kāi)發(fā),軟件要完成的功能并沒(méi)有變化,還是客戶要求的所有功能,也就是“事情還是那些事情”的意思。但是有了框架過(guò)后,框架完成了一部分功能,然后開(kāi)發(fā)人員再完成一部分功能,最后由框架和開(kāi)發(fā)人員合起

9、來(lái)完成了整個(gè)軟件的功能,也就是看這些功能“由誰(shuí)做”的問(wèn)題。         基于框架開(kāi)發(fā),可以不去做框架所做的事情,但是應(yīng)該明白框架在干什么,以及框架是如何實(shí)現(xiàn)相應(yīng)功能的        事實(shí)上,在實(shí)際開(kāi)發(fā)中,應(yīng)用程序和框架的關(guān)系,通常都不會(huì)如上面講述的那樣,分得那么清楚,更為普遍的是相互交互的,也就是應(yīng)用程序做一部分工作,然后框架做一部分工作,然后應(yīng)用程序再做一部分工作,然后框架再做一部分工作,如此交錯(cuò),最后由應(yīng)用程序和框架組合起來(lái)完成用戶的功能

10、要求。        也用個(gè)圖來(lái)說(shuō)明,如圖2所示:             圖2  應(yīng)用程序和框架的關(guān)系示意圖        如果把這個(gè)由應(yīng)用程序和框架組合在一起構(gòu)成的矩形,當(dāng)作最后完成的軟件。試想一下,如果你不懂框架在干什么的話,相當(dāng)于框架對(duì)你來(lái)講是個(gè)黑盒,也就是相當(dāng)于在上面圖2中,去掉框架的兩塊,會(huì)發(fā)現(xiàn)什么?沒(méi)錯(cuò),剩下的應(yīng)用

11、程序是支離破碎的,是相互分隔開(kāi)來(lái)的。        這會(huì)導(dǎo)致一個(gè)非常致命的問(wèn)題,整個(gè)應(yīng)用是如何運(yùn)轉(zhuǎn)起來(lái)的,你是不清楚的,也就是說(shuō)對(duì)你而言,項(xiàng)目已經(jīng)失控了,從項(xiàng)目管理的角度來(lái)講,這是很危險(xiǎn)的。        因此,在基于框架開(kāi)發(fā)的時(shí)候,雖然我們可以不去做框架所做的事情,但是應(yīng)該搞明白框架在干什么,如果條件許可的話,還應(yīng)該搞清楚框架是如何實(shí)現(xiàn)相應(yīng)功能的,至少應(yīng)該把大致的實(shí)現(xiàn)思路和實(shí)現(xiàn)步驟搞清楚,這樣我們才能整體的掌控整個(gè)項(xiàng)目,才能盡量減少出現(xiàn)項(xiàng)目失控的情況。(

12、4):框架和設(shè)計(jì)模式的關(guān)系        設(shè)計(jì)模式比框架更抽象       框架已經(jīng)是實(shí)現(xiàn)出來(lái)的軟件了,雖然只是個(gè)半成品的軟件,但畢竟是已經(jīng)實(shí)現(xiàn)出來(lái)的了。而設(shè)計(jì)模式的重心還在于解決問(wèn)題的方案上,也就是還停留在思想的層面。因此設(shè)計(jì)模式比框架更為抽象。              設(shè)計(jì)模式是比框架更小的體系結(jié)構(gòu)元素   &#

13、160;   如上所述,框架是已經(jīng)實(shí)現(xiàn)出來(lái)的軟件,并實(shí)現(xiàn)了一系列的功能,因此一個(gè)框架,通常會(huì)包含多個(gè)設(shè)計(jì)模式的應(yīng)用。        框架比設(shè)計(jì)模式更加特例化       框架是完成一定功能的半成品軟件,也就是說(shuō),框架的目的很明確,就是要解決某一個(gè)領(lǐng)域的某些問(wèn)題,那是很具體的功能,不同的領(lǐng)域?qū)崿F(xiàn)出來(lái)的框架是不一樣的。      而設(shè)計(jì)模式還停留在思想的層面,在不同的領(lǐng)域都可以應(yīng)用,只要相應(yīng)的問(wèn)題適合

14、用某個(gè)設(shè)計(jì)模式來(lái)解決。因此框架總是針對(duì)特定領(lǐng)域的,而設(shè)計(jì)模式更加注重從思想上,從方法上來(lái)解決問(wèn)題,更加通用化。1.3  有何問(wèn)題       分析上面要實(shí)現(xiàn)的應(yīng)用框架,不管用戶選擇什么樣的導(dǎo)出格式,最后導(dǎo)出的都是一個(gè)文件,而且系統(tǒng)并不知道究竟要導(dǎo)出成為什么樣的文件,因此應(yīng)該有一個(gè)統(tǒng)一的接口,來(lái)描述系統(tǒng)最后生成的對(duì)象,并操作輸出的文件。       先把導(dǎo)出的文件對(duì)象的接口定義出來(lái),示例代碼如下:  /* * 導(dǎo)出的文件對(duì)象的接口

15、0;*/public interface ExportFileApi     /*     * 導(dǎo)出內(nèi)容成為文件     * param data 示意:需要保存的數(shù)據(jù)     * return 是否導(dǎo)出成功     */    public boolean export(String data);      

16、0; 對(duì)于實(shí)現(xiàn)導(dǎo)出數(shù)據(jù)的業(yè)務(wù)功能對(duì)象,它應(yīng)該根據(jù)需要來(lái)創(chuàng)建相應(yīng)的ExportFileApi的實(shí)現(xiàn)對(duì)象,因?yàn)樘囟ǖ腅xportFileApi的實(shí)現(xiàn)是與具體的業(yè)務(wù)相關(guān)的。但是對(duì)于實(shí)現(xiàn)導(dǎo)出數(shù)據(jù)的業(yè)務(wù)功能對(duì)象而言,它并不知道應(yīng)該創(chuàng)建哪一個(gè)ExportFileApi的實(shí)現(xiàn)對(duì)象,也不知道如何創(chuàng)建。        也就是說(shuō):對(duì)于實(shí)現(xiàn)導(dǎo)出數(shù)據(jù)的業(yè)務(wù)功能對(duì)象,它需要?jiǎng)?chuàng)建ExportFileApi的具體實(shí)例對(duì)象,但是它只知道ExportFileApi接口,而不知道其具體的實(shí)現(xiàn)。那該怎么辦呢?研磨設(shè)計(jì)模式之 工廠方法模式-2  

17、;2  解決方案2.1  工廠方法模式來(lái)解決        用來(lái)解決上述問(wèn)題的一個(gè)合理的解決方案就是工廠方法模式。那么什么是工廠方法模式呢?(1)工廠方法模式定義        定義一個(gè)用于創(chuàng)建對(duì)象的接口,讓子類決定實(shí)例化哪一個(gè)類,F(xiàn)actory Method使一個(gè)類的實(shí)例化延遲到其子類。 (2)應(yīng)用工廠方法模式來(lái)解決的思路        仔細(xì)分析上面的問(wèn)題

18、,事實(shí)上在實(shí)現(xiàn)導(dǎo)出數(shù)據(jù)的業(yè)務(wù)功能對(duì)象里面,根本就不知道究竟要使用哪一種導(dǎo)出文件的格式,因此這個(gè)對(duì)象本就不應(yīng)該和具體的導(dǎo)出文件的對(duì)象耦合在一起,它只需要面向?qū)С龅奈募?duì)象的接口就好了。        但是這樣一來(lái),又有新的問(wèn)題產(chǎn)生了:接口是不能直接使用的,需要使用具體的接口實(shí)現(xiàn)對(duì)象的實(shí)例。        這不是自相矛盾嗎?要求面向接口,不讓和具體的實(shí)現(xiàn)耦合,但是又需要?jiǎng)?chuàng)建接口的具體實(shí)現(xiàn)對(duì)象的實(shí)例。怎么解決這個(gè)矛盾呢?   

19、60;    工廠方法模式的解決思路很有意思,那就是不解決,采取無(wú)為而治的方式:不是需要接口對(duì)象嗎,那就定義一個(gè)方法來(lái)創(chuàng)建;可是事實(shí)上它自己是不知道如何創(chuàng)建這個(gè)接口對(duì)象的,沒(méi)有關(guān)系,那就定義成抽象方法就好了,自己實(shí)現(xiàn)不了,那就讓子類來(lái)實(shí)現(xiàn),這樣這個(gè)對(duì)象本身就可以只是面向接口編程,而無(wú)需關(guān)心到底如何創(chuàng)建接口對(duì)象了。2.2  模式結(jié)構(gòu)和說(shuō)明        工廠方法模式的結(jié)構(gòu)如圖3所示:         

20、;            圖3  工廠方法模式結(jié)構(gòu)示意圖Product:        定義工廠方法所創(chuàng)建的對(duì)象的接口,也就是實(shí)際需要使用的對(duì)象的接口。ConcreteProduct:        具體的Product接口的實(shí)現(xiàn)對(duì)象。Creator:        創(chuàng)

21、建器,聲明工廠方法,工廠方法通常會(huì)返回一個(gè)Product類型的實(shí)例對(duì)象,而且多是抽象方法。也可以在Creator里面提供工廠方法的默認(rèn)實(shí)現(xiàn),讓工廠方法返回一個(gè)缺省的Product類型的實(shí)例對(duì)象。ConcreteCreator:        具體的創(chuàng)建器對(duì)象,覆蓋實(shí)現(xiàn)Creator定義的工廠方法,返回具體的Product實(shí)例。2.3  工廠方法模式示例代碼(1)先看看Product的定義,示例代碼如下:/* * 工廠方法所創(chuàng)建的對(duì)象的接口 */public interface Product &

22、#160;   /可以定義Product的屬性和方法(2)再看看具體的Product的實(shí)現(xiàn)對(duì)象,示例代碼如下: /* * 具體的Product對(duì)象 */public class ConcreteProduct implements Product     /實(shí)現(xiàn)Product要求的方法(3)接下來(lái)看看創(chuàng)建器的定義,示例代碼如下: /* * 創(chuàng)建器,聲明工廠方法 */public abstract class Creator     /* 

23、0;   * 創(chuàng)建Product的工廠方法     * return Product對(duì)象     */    protected abstract Product factoryMethod();    /*     * 示意方法,實(shí)現(xiàn)某些功能的方法      */    public void someOperation()

24、       /通常在這些方法實(shí)現(xiàn)中,需要調(diào)用工廠方法來(lái)獲取Product對(duì)象       Product product = factoryMethod();    (4)再看看具體的創(chuàng)建器實(shí)現(xiàn)對(duì)象,示例代碼如下: /* * 具體的創(chuàng)建器實(shí)現(xiàn)對(duì)象 */public class ConcreteCreator extends Creator     protected Product f

25、actoryMethod()        /重定義工廠方法,返回一個(gè)具體的Product對(duì)象       return new ConcreteProduct();     2.4  使用工廠方法模式來(lái)實(shí)現(xiàn)示例        要使用工廠方法模式來(lái)實(shí)現(xiàn)示例,先來(lái)按照工廠方法模式的結(jié)構(gòu),對(duì)應(yīng)出哪些是被創(chuàng)建的Product,哪些是Creator。分析要求實(shí)現(xiàn)的功

26、能,導(dǎo)出的文件對(duì)象接口ExportFileApi就相當(dāng)于是Product,而用來(lái)實(shí)現(xiàn)導(dǎo)出數(shù)據(jù)的業(yè)務(wù)功能對(duì)象就相當(dāng)于Creator。把Product和Creator分開(kāi)過(guò)后,就可以分別來(lái)實(shí)現(xiàn)它們了。        使用工廠模式來(lái)實(shí)現(xiàn)示例的程序結(jié)構(gòu)如圖4所示:                       

27、;          圖4  使用工廠模式來(lái)實(shí)現(xiàn)示例的程序結(jié)構(gòu)示意圖 下面一起來(lái)看看代碼實(shí)現(xiàn)。(1)導(dǎo)出的文件對(duì)象接口ExportFileApi的實(shí)現(xiàn)沒(méi)有變化,這里就不去贅述了(2)接下來(lái)看看接口ExportFileApi的實(shí)現(xiàn),為了示例簡(jiǎn)單,只實(shí)現(xiàn)導(dǎo)出文本文件格式和數(shù)據(jù)庫(kù)備份文件兩種。先看看導(dǎo)出文本文件格式的實(shí)現(xiàn),示例代碼如下: /* * 導(dǎo)出成文本文件格式的對(duì)象 */public class ExportTxtFile implements Expor

28、tFileApi    public boolean export(String data)        /簡(jiǎn)單示意一下,這里需要操作文件       System.out.println("導(dǎo)出數(shù)據(jù)"+data+"到文本文件");       return true;    再看看導(dǎo)出成數(shù)據(jù)庫(kù)備份文件形式的對(duì)象的實(shí)

29、現(xiàn),示例代碼如下:  /* * 導(dǎo)出成數(shù)據(jù)庫(kù)備份文件形式的對(duì)象 */public class ExportDB implements ExportFileApi    public boolean export(String data)        /簡(jiǎn)單示意一下,這里需要操作數(shù)據(jù)庫(kù)和文件       System.out.println("導(dǎo)出數(shù)據(jù)"+data+"到數(shù)據(jù)庫(kù)備

30、份文件");       return true;    (3)Creator這邊的實(shí)現(xiàn),首先看看ExportOperate的實(shí)現(xiàn),示例代碼如下: /* * 實(shí)現(xiàn)導(dǎo)出數(shù)據(jù)的業(yè)務(wù)功能對(duì)象 */public abstract class ExportOperate     /*     * 導(dǎo)出文件     * param data 需要保存的數(shù)據(jù) &

31、#160;   * return 是否成功導(dǎo)出文件     */    public boolean export(String data)       /使用工廠方法       ExportFileApi api = factoryMethod();       return api.export(data); &

32、#160;      /*     * 工廠方法,創(chuàng)建導(dǎo)出的文件對(duì)象的接口對(duì)象     * return 導(dǎo)出的文件對(duì)象的接口對(duì)象     */    protected abstract ExportFileApi factoryMethod();(4)加入了兩個(gè)Creator實(shí)現(xiàn),先看看創(chuàng)建導(dǎo)出成文本文件格式的對(duì)象,示例代碼如下:  /* * 具體的創(chuàng)建器實(shí)現(xiàn)對(duì)象,實(shí)現(xiàn)創(chuàng)建

33、導(dǎo)出成文本文件格式的對(duì)象 */public class ExportTxtFileOperate extends ExportOperate    protected ExportFileApi factoryMethod()        /創(chuàng)建導(dǎo)出成文本文件格式的對(duì)象       return new ExportTxtFile();    再看看創(chuàng)建導(dǎo)出成數(shù)據(jù)庫(kù)備份文件形式的對(duì)象,示例代碼如下:

34、60; /* * 具體的創(chuàng)建器實(shí)現(xiàn)對(duì)象,實(shí)現(xiàn)創(chuàng)建導(dǎo)出成數(shù)據(jù)庫(kù)備份文件形式的對(duì)象 */public class ExportDBOperate extends ExportOperate    protected ExportFileApi factoryMethod()        /創(chuàng)建導(dǎo)出成數(shù)據(jù)庫(kù)備份文件形式的對(duì)象       return new ExportDB();    (

35、5)客戶端直接創(chuàng)建需要使用的Creator對(duì)象,然后調(diào)用相應(yīng)的功能方法,示例代碼如下:  public class Client     public static void main(String args)        /創(chuàng)建需要使用的Creator對(duì)象       ExportOperate operate = new ExportDBOperate();     &#

36、160; /調(diào)用輸出數(shù)據(jù)的功能方法       operate.export("測(cè)試數(shù)據(jù)");    運(yùn)行結(jié)果如下:  導(dǎo)出數(shù)據(jù)測(cè)試數(shù)據(jù)到數(shù)據(jù)庫(kù)備份文件         你還可以修改客戶端new的對(duì)象,切換成其它的實(shí)現(xiàn)對(duì)象,試試看會(huì)發(fā)生什么??磥?lái)應(yīng)用工廠方法模式是很簡(jiǎn)單的,對(duì)吧。研磨設(shè)計(jì)模式之 工廠方法模式-33  模式講解3.1  認(rèn)識(shí)工廠方法模式(1)模式的功能&

37、#160;       工廠方法的主要功能是讓父類在不知道具體實(shí)現(xiàn)的情況下,完成自身的功能調(diào)用,而具體的實(shí)現(xiàn)延遲到子類來(lái)實(shí)現(xiàn)。        這樣在設(shè)計(jì)的時(shí)候,不用去考慮具體的實(shí)現(xiàn),需要某個(gè)對(duì)象,把它通過(guò)工廠方法返回就好了,在使用這些對(duì)象實(shí)現(xiàn)功能的時(shí)候還是通過(guò)接口來(lái)操作,這非常類似于IoC/DI的思想,這個(gè)在后面給大家稍詳細(xì)點(diǎn)介紹一下。(2)實(shí)現(xiàn)成抽象類        工廠方法的實(shí)現(xiàn)中,通常父類會(huì)

38、是一個(gè)抽象類,里面包含創(chuàng)建所需對(duì)象的抽象方法,這些抽象方法就是工廠方法。        這里要注意一個(gè)問(wèn)題,子類在實(shí)現(xiàn)這些抽象方法的時(shí)候,通常并不是真的由子類來(lái)實(shí)現(xiàn)具體的功能,而是在子類的方法里面做選擇,選擇具體的產(chǎn)品實(shí)現(xiàn)對(duì)象。        父類里面,通常會(huì)有使用這些產(chǎn)品對(duì)象來(lái)實(shí)現(xiàn)一定的功能的方法,而且這些方法所實(shí)現(xiàn)的功能通常都是公共的功能,不管子類選擇了何種具體的產(chǎn)品實(shí)現(xiàn),這些方法的功能總是能正確執(zhí)行。(3)實(shí)現(xiàn)成具體的類  

39、60;     當(dāng)然也可以把父類實(shí)現(xiàn)成為一個(gè)具體的類,這種情況下,通常是在父類中提供獲取所需對(duì)象的默認(rèn)實(shí)現(xiàn)方法,這樣就算沒(méi)有具體的子類,也能夠運(yùn)行。        通常這種情況還是需要具體的子類來(lái)決定具體要如何創(chuàng)建父類所需要的對(duì)象。也把這種情況稱為工廠方法為子類提供了掛鉤,通過(guò)工廠方法,可以讓子類對(duì)象來(lái)覆蓋父類的實(shí)現(xiàn),從而提供更好的靈活性。(4)工廠方法的參數(shù)和返回        工廠方法的實(shí)現(xiàn)中,可能需要參數(shù),以便

40、決定到底選用哪一種具體的實(shí)現(xiàn)。也就是說(shuō)通過(guò)在抽象方法里面?zhèn)鬟f參數(shù),在子類實(shí)現(xiàn)的時(shí)候根據(jù)參數(shù)進(jìn)行選擇,看看究竟應(yīng)該創(chuàng)建哪一個(gè)具體的實(shí)現(xiàn)對(duì)象。        一般工廠方法返回的是被創(chuàng)建對(duì)象的接口對(duì)象,當(dāng)然也可以是抽象類或者一個(gè)具體的類的實(shí)例。(5)誰(shuí)來(lái)使用工廠方法創(chuàng)建的對(duì)象        這里首先要搞明白一件事情,就是誰(shuí)在使用工廠方法創(chuàng)建的對(duì)象?        事實(shí)上,在工廠方法模式里面,應(yīng)

41、該是Creator中的其它方法在使用工廠方法創(chuàng)建的對(duì)象,雖然也可以把工廠方法創(chuàng)建的對(duì)象直接提供給Creator外部使用,但工廠方法模式的本意,是由Creator對(duì)象內(nèi)部的方法來(lái)使用工廠方法創(chuàng)建的對(duì)象,也就是說(shuō),工廠方法一般不提供給Creator外部使用。        客戶端應(yīng)該是使用Creator對(duì)象,或者是使用由Creator創(chuàng)建出來(lái)的對(duì)象。對(duì)于客戶端使用Creator對(duì)象,這個(gè)時(shí)候工廠方法創(chuàng)建的對(duì)象,是Creator中的某些方法使用。對(duì)于使用那些由Creator創(chuàng)建出來(lái)的對(duì)象,這個(gè)時(shí)候工廠方法創(chuàng)建的對(duì)象,是構(gòu)成客戶端需

42、要的對(duì)象的一部分。分別舉例來(lái)說(shuō)明。    客戶端使用Creator對(duì)象的情況        比如前面的示例,對(duì)于“實(shí)現(xiàn)導(dǎo)出數(shù)據(jù)的業(yè)務(wù)功能對(duì)象”的類ExportOperate,它有一個(gè)export的方法,在這個(gè)方法里面,需要使用具體的“導(dǎo)出的文件對(duì)象的接口對(duì)象” ExportFileApi,而ExportOperate是不知道具體的ExportFileApi實(shí)現(xiàn)的,那么怎么做的呢?就是定義了一個(gè)工廠方法,用來(lái)返回ExportFileApi的對(duì)象,然后export方法會(huì)使用這個(gè)工廠方法來(lái)獲取它所需要

43、的對(duì)象,然后執(zhí)行功能。        這個(gè)時(shí)候的客戶端是怎么做的呢?這個(gè)時(shí)候客戶端主要就是使用這個(gè)ExportOperate的實(shí)例來(lái)完成它想要完成的功能,也就是客戶端使用Creator對(duì)象的情況,簡(jiǎn)單描述這種情況下的代碼結(jié)構(gòu)如下: /* * 客戶端使用Creator對(duì)象的情況下,Creator的基本實(shí)現(xiàn)結(jié)構(gòu) */public abstract class Creator     /*     * 工廠方法,一般不對(duì)外 

44、;    * return 創(chuàng)建的產(chǎn)品對(duì)象     */    protected abstract Product factoryMethod();    /*     * 提供給外部使用的方法,     * 客戶端一般使用Creator提供的這些方法來(lái)完成所需要的功能     */    public void s

45、omeOperation()       /在這里使用工廠方法       Product p = factoryMethod();     客戶端使用由Creator創(chuàng)建出來(lái)的對(duì)象        另外一種是由Creator向客戶端返回由“工廠方法創(chuàng)建的對(duì)象”來(lái)構(gòu)建的對(duì)象,這個(gè)時(shí)候工廠方法創(chuàng)建的對(duì)象,是構(gòu)成客戶端需要的對(duì)象的一部分。簡(jiǎn)單描述這種情況下的代碼結(jié)構(gòu)如下:&

46、#160;/* * 客戶端使用Creator來(lái)創(chuàng)建客戶端需要的對(duì)象的情況下,Creator的基本實(shí)現(xiàn)結(jié)構(gòu) */public abstract class Creator     /*     * 工廠方法,一般不對(duì)外,創(chuàng)建一個(gè)部件對(duì)象     * return 創(chuàng)建的產(chǎn)品對(duì)象,一般是另一個(gè)產(chǎn)品對(duì)象的部件     */    protected abstract Product1 factoryMe

47、thod1();    /*     * 工廠方法,一般不對(duì)外,創(chuàng)建一個(gè)部件對(duì)象     * return 創(chuàng)建的產(chǎn)品對(duì)象,一般是另一個(gè)產(chǎn)品對(duì)象的部件     */    protected abstract Product2 factoryMethod2();    /*     * 創(chuàng)建客戶端需要的對(duì)象,客戶端主要使用產(chǎn)品對(duì)象來(lái)完成所需要的功能

48、     * return 客戶端需要的對(duì)象     */    public Product createProduct()       /在這里使用工廠方法,得到客戶端所需對(duì)象的部件對(duì)象       Product1 p1 = factoryMethod1();       Product2 p2 = f

49、actoryMethod2();        /工廠方法創(chuàng)建的對(duì)象是創(chuàng)建客戶端對(duì)象所需要的       Product p = new ConcreteProduct();       p.setProduct1(p1);       p.setProduct2(p2);       &

50、#160;      return p;            小結(jié)一下:在工廠方法模式里面,客戶端要么使用Creator對(duì)象,要么使用Creator創(chuàng)建的對(duì)象,一般客戶端不直接使用工廠方法。當(dāng)然也可以直接把工廠方法暴露給客戶端操作,但是一般不這么做。(6)工廠方法模式的調(diào)用順序示意圖        由于客戶端使用Creator對(duì)象有兩種典型的情況,因此調(diào)用的順序示意圖也分做兩

51、種情況,先看看客戶端使用由Creator創(chuàng)建出來(lái)的對(duì)象情況的調(diào)用順序示意圖,如圖5所示:             圖5  客戶端使用由Creator創(chuàng)建出來(lái)的對(duì)象的調(diào)用順序示意圖接下來(lái)看看客戶端使用Creator對(duì)象時(shí)候的調(diào)用順序示意圖,如圖6所示:              圖6  客戶端使用Creator對(duì)象的調(diào)用順序示意圖

52、研磨設(shè)計(jì)模式之 工廠方法模式-43.2  工廠方法模式與IoC/DI IoCInversion of Control  控制反轉(zhuǎn) DIDependency Injection   依賴注入1:如何理解IoC/DI        要想理解上面兩個(gè)概念,就必須搞清楚如下的問(wèn)題:· 參與者都有誰(shuí)? · 依賴:誰(shuí)依賴于誰(shuí)?為什么需要依賴?  · 注入:誰(shuí)注入于誰(shuí)?到底注入什么? · 控制反轉(zhuǎn):誰(shuí)控制誰(shuí)?控制什么?為何叫反轉(zhuǎn)(

53、有反轉(zhuǎn)就應(yīng)該有正轉(zhuǎn)了)? · 依賴注入和控制反轉(zhuǎn)是同一概念嗎?         下面就來(lái)簡(jiǎn)要的回答一下上述問(wèn)題,把這些問(wèn)題搞明白了,IoC/DI也就明白了。(1)參與者都有誰(shuí):        一般有三方參與者,一個(gè)是某個(gè)對(duì)象;一個(gè)是IoC/DI的容器;另一個(gè)是某個(gè)對(duì)象的外部資源。        又要名詞解釋一下,某個(gè)對(duì)象指的就是任意的、普通的Java對(duì)象; IoC/DI的容器簡(jiǎn)

54、單點(diǎn)說(shuō)就是指用來(lái)實(shí)現(xiàn)IoC/DI功能的一個(gè)框架程序;對(duì)象的外部資源指的就是對(duì)象需要的,但是是從對(duì)象外部獲取的,都統(tǒng)稱資源,比如:對(duì)象需要的其它對(duì)象、或者是對(duì)象需要的文件資源等等。(2)誰(shuí)依賴于誰(shuí):        當(dāng)然是某個(gè)對(duì)象依賴于IoC/DI的容器(3)為什么需要依賴:        對(duì)象需要IoC/DI的容器來(lái)提供對(duì)象需要的外部資源(4)誰(shuí)注入于誰(shuí):       

55、 很明顯是IoC/DI的容器 注入 某個(gè)對(duì)象(5)到底注入什么:        就是注入某個(gè)對(duì)象所需要的外部資源(6)誰(shuí)控制誰(shuí):        當(dāng)然是IoC/DI的容器來(lái)控制對(duì)象了(7)控制什么:        主要是控制對(duì)象實(shí)例的創(chuàng)建(8)為何叫反轉(zhuǎn):        反轉(zhuǎn)是相對(duì)

56、于正向而言的,那么什么算是正向的呢?考慮一下常規(guī)情況下的應(yīng)用程序,如果要在A里面使用C,你會(huì)怎么做呢?當(dāng)然是直接去創(chuàng)建C的對(duì)象,也就是說(shuō),是在A類中主動(dòng)去獲取所需要的外部資源C,這種情況被稱為正向的。那么什么是反向呢?就是A類不再主動(dòng)去獲取C,而是被動(dòng)等待,等待IoC/DI的容器獲取一個(gè)C的實(shí)例,然后反向的注入到A類中。        用圖例來(lái)說(shuō)明一下,先看沒(méi)有IoC/DI的時(shí)候,常規(guī)的A類使用C類的示意圖,如圖7所示:         

57、;                             圖7  常規(guī)A使用C示意圖當(dāng)有了IoC/DI的容器后,A類不再主動(dòng)去創(chuàng)建C了,如圖8所示:             &#

58、160;                       圖8  A類不再主動(dòng)創(chuàng)建C而是被動(dòng)等待,等待IoC/DI的容器獲取一個(gè)C的實(shí)例,然后反向的注入到A類中,如圖9所示:                

59、0;                              圖9  有IoC/DI容器后程序結(jié)構(gòu)示意圖(9)依賴注入和控制反轉(zhuǎn)是同一概念嗎?        根據(jù)上面的講述,應(yīng)該能看出來(lái),依賴注入和控制反轉(zhuǎn)是對(duì)同一件事

60、情的不同描述,從某個(gè)方面講,就是它們描述的角度不同。依賴注入是從應(yīng)用程序的角度在描述,可以把依賴注入描述完整點(diǎn):應(yīng)用程序依賴容器創(chuàng)建并注入它所需要的外部資源;而控制反轉(zhuǎn)是從容器的角度在描述,描述完整點(diǎn):容器控制應(yīng)用程序,由容器反向的向應(yīng)用程序注入應(yīng)用程序所需要的外部資源。(10)小結(jié)一下:        其實(shí)IoC/DI對(duì)編程帶來(lái)的最大改變不是從代碼上,而是從思想上,發(fā)生了“主從換位”的變化。應(yīng)用程序原本是老大,要獲取什么資源都是主動(dòng)出擊,但是在IoC/DI思想中,應(yīng)用程序就變成被動(dòng)的了,被動(dòng)的等待IoC/DI容器來(lái)創(chuàng)建并注

61、入它所需要的資源了。        這么小小的一個(gè)改變其實(shí)是編程思想的一個(gè)大進(jìn)步,這樣就有效的分離了對(duì)象和它所需要的外部資源,使得它們松散耦合,有利于功能復(fù)用,更重要的是使得程序的整個(gè)體系結(jié)構(gòu)變得非常靈活。2:工廠方法模式和IoC/DI有什么關(guān)系呢?        從某個(gè)角度講,它們的思想很類似。        上面講了,有了IoC/DI過(guò)后,應(yīng)用程序就不再主動(dòng)了,而是被動(dòng)等待由容器來(lái)注

62、入資源,那么在編寫代碼的時(shí)候,一旦要用到外部資源,就會(huì)開(kāi)一個(gè)窗口,讓容器能注入進(jìn)來(lái),也就是提供給容器使用的注入的途徑,當(dāng)然這不是我們的重點(diǎn),就不去細(xì)細(xì)講了,用setter注入來(lái)示例一下,看看使用IoC/DI的代碼是什么樣子,示例代碼如下: public class A     /*     * 等待被注入進(jìn)來(lái)     */    private C c = null;    /*   

63、 * 注入資源C的方法     * param c 被注入的資源     */    public void setC(C c)       this.c = c;        public void t1()       /這里需要使用C,可是又不讓主動(dòng)去創(chuàng)建C了,怎么辦?  

64、;     /反正就要求從外部注入,這樣更省心,       /自己不用管怎么獲取C,直接使用就好了       c.tc();    接口C的示例代碼如下: public interface C     public void tc();         從上面的示例代碼可以看出,現(xiàn)在在

65、A里面寫代碼的時(shí)候,凡是碰到了需要外部資源,那么就提供注入的途徑,要求從外部注入,自己只管使用這些對(duì)象。        再來(lái)看看工廠方法模式,如何實(shí)現(xiàn)上面同樣的功能,為了區(qū)分,分別取名為A1和C1。這個(gè)時(shí)候在A1里面要使用C1對(duì)象,也不是由A1主動(dòng)去獲取C1對(duì)象,而是創(chuàng)建一個(gè)工廠方法,就類似于一個(gè)注入的途徑;然后由子類,假設(shè)叫A2吧,由A2來(lái)獲取C1對(duì)象,在調(diào)用的時(shí)候,替換掉A1的相應(yīng)方法,相當(dāng)于反向注入回到A1里面,示例代碼如下: public abstract class A1   

66、0; /*     * 工廠方法,創(chuàng)建C1,類似于從子類注入進(jìn)來(lái)的途徑     * return C1的對(duì)象實(shí)例     */    protected abstract C1 createC1();    public void t1()       /這里需要使用C1類,可是不知道究竟是用哪一個(gè)     

67、  /也就不主動(dòng)去創(chuàng)建C1了,怎么辦?       /反正會(huì)在子類里面實(shí)現(xiàn),這里不用管怎么獲取C1,直接使用就好了       createC1().tc();    子類的示例代碼如下: public class A2 extends A1     protected C1 createC1()        /真正的選擇具體

68、實(shí)現(xiàn),并創(chuàng)建對(duì)象       return new C2();             C1接口和前面C接口是一樣的,C2這個(gè)實(shí)現(xiàn)類也是空的,只是演示一下,因此就不去展示它們的代碼了。        仔細(xì)體會(huì)上面的示例,對(duì)比它們的實(shí)現(xiàn),尤其是從思想層面上,會(huì)發(fā)現(xiàn)工廠方法模式和IoC/DI的思想是相似的,都是“主動(dòng)變被動(dòng)”,進(jìn)行了“主從換位”,從而獲得了更靈活

69、的程序結(jié)構(gòu)。研磨設(shè)計(jì)模式之 工廠方法模式-53.3  平行的類層次結(jié)構(gòu)(1)什么是平行的類層次結(jié)構(gòu)呢? 簡(jiǎn)單點(diǎn)說(shuō),假如有兩個(gè)類層次結(jié)構(gòu),其中一個(gè)類層次中的每個(gè)類在另一個(gè)類層次中都有一個(gè)對(duì)應(yīng)的類的結(jié)構(gòu),就被稱為平行的類層次結(jié)構(gòu)。舉個(gè)例子來(lái)說(shuō),硬盤對(duì)象有很多種,如分成臺(tái)式機(jī)硬盤和筆記本硬盤,在臺(tái)式機(jī)硬盤的具體實(shí)現(xiàn)上面,又有希捷、西數(shù)等不同品牌的實(shí)現(xiàn),同樣在筆記本硬盤上,也有希捷、日立、IBM等不同品牌的實(shí)現(xiàn);硬盤對(duì)象具有自己的行為,如硬盤能存儲(chǔ)數(shù)據(jù),也能從硬盤上獲取數(shù)據(jù),不同的硬盤對(duì)象對(duì)應(yīng)的行為對(duì)象是不一樣的,因?yàn)椴煌挠脖P對(duì)象,它的行為的實(shí)現(xiàn)方式是不一樣的。如果把硬盤對(duì)象和硬

70、盤對(duì)象的行為分開(kāi)描述,那么就構(gòu)成了如圖10所示的結(jié)構(gòu):圖10  平行的類層次結(jié)構(gòu)示意圖硬盤對(duì)象是一個(gè)類層次,硬盤的行為這邊也是一個(gè)類層次,而且兩個(gè)類層次中的類是對(duì)應(yīng)的。臺(tái)式機(jī)西捷硬盤對(duì)象就對(duì)應(yīng)著硬盤行為里面的臺(tái)式機(jī)西捷硬盤的行為;筆記本IBM硬盤就對(duì)應(yīng)著筆記本IBM硬盤的行為,這就是一種典型的平行的類層次結(jié)構(gòu)。這種平行的類層次結(jié)構(gòu)用來(lái)干什么呢?主要用來(lái)把一個(gè)類層次中的某些行為分離出來(lái),讓類層次中的類把原本屬于自己的職責(zé),委托給分離出來(lái)的類去實(shí)現(xiàn),從而使得類層次本身變得更簡(jiǎn)單,更容易擴(kuò)展和復(fù)用。一般來(lái)講,分離出去的這些類的行為,會(huì)對(duì)應(yīng)著類層次結(jié)構(gòu)來(lái)組織,從而形成一個(gè)新的類層次結(jié)構(gòu),相當(dāng)

71、于原來(lái)對(duì)象的行為的這么一個(gè)類層次結(jié)構(gòu),而這個(gè)層次結(jié)構(gòu)和原來(lái)的類層次結(jié)構(gòu)是存在對(duì)應(yīng)關(guān)系的,因此被稱為平行的類層次結(jié)構(gòu)。(2)工廠方法模式跟平行的類層次結(jié)構(gòu)有何關(guān)系呢?可以使用工廠方法模式來(lái)連接平行的類層次??瓷厦娴氖纠龍D10,在每個(gè)硬盤對(duì)象里面,都有一個(gè)工廠方法createHDOperate,通過(guò)這個(gè)工廠方法,客戶端就可以獲取一個(gè)跟硬盤對(duì)象相對(duì)應(yīng)的行為對(duì)象。在硬盤對(duì)象的子類里面,會(huì)覆蓋父類的工廠方法createHDOperate,以提供跟自身相對(duì)應(yīng)的行為對(duì)象,從而自然的把兩個(gè)平行的類層次連接起來(lái)使用。3.4  參數(shù)化工廠方法所謂參數(shù)化工廠方法指的就是:通過(guò)給工廠方法傳遞參數(shù),讓工廠方法

72、根據(jù)參數(shù)的不同來(lái)創(chuàng)建不同的產(chǎn)品對(duì)象,這種情況就被稱為參數(shù)化工廠方法。當(dāng)然工廠方法創(chuàng)建的不同的產(chǎn)品必須是同一個(gè)Product類型的。來(lái)改造前面的示例,現(xiàn)在有一個(gè)工廠方法來(lái)創(chuàng)建ExportFileApi這個(gè)產(chǎn)品的對(duì)象,但是ExportFileApi接口的具體實(shí)現(xiàn)很多,為了方便創(chuàng)建的選擇,直接從客戶端傳入一個(gè)參數(shù),這樣在需要?jiǎng)?chuàng)建ExportFileApi對(duì)象的時(shí)候,就把這個(gè)參數(shù)傳遞給工廠方法,讓工廠方法來(lái)實(shí)例化具體的ExportFileApi實(shí)現(xiàn)對(duì)象。還是看看代碼示例會(huì)比較清楚。(1)先來(lái)看Product的接口,就是ExportFileApi接口,跟前面的示例沒(méi)有任何變化,為了方便大家查看,這里重復(fù)

73、一下,示例代碼如下: /* * 導(dǎo)出的文件對(duì)象的接口 */public interface ExportFileApi     /*     * 導(dǎo)出內(nèi)容成為文件     * param data 示意:需要保存的數(shù)據(jù)     * return 是否導(dǎo)出成功     */    public boolean export(String data);

74、 (2)同樣提供保存成文本文件和保存成數(shù)據(jù)庫(kù)備份文件的實(shí)現(xiàn),跟前面的示例沒(méi)有任何變化,示例代碼如下: public class ExportTxtFile implements ExportFileApi    public boolean export(String data)        /簡(jiǎn)單示意一下,這里需要操作文件       System.out.println("導(dǎo)出數(shù)據(jù)"+data+&qu

75、ot;到文本文件");       return true;    public class ExportDB implements ExportFileApi    public boolean export(String data)        /簡(jiǎn)單示意一下,這里需要操作數(shù)據(jù)庫(kù)和文件       System.out.println(&qu

76、ot;導(dǎo)出數(shù)據(jù)"+data+"到數(shù)據(jù)庫(kù)備份文件");       return true;     (3)接下來(lái)該看看ExportOperate類了,這個(gè)類的變化大致如下:· ExportOperate類中的創(chuàng)建產(chǎn)品的工廠方法,通常需要提供默認(rèn)的實(shí)現(xiàn),不抽象了,也就是變成正常方法 · ExportOperate類也不再定義成抽象類了,因?yàn)橛辛四J(rèn)的實(shí)現(xiàn),客戶端可能需要直接使用這個(gè)對(duì)象 · 設(shè)置一個(gè)導(dǎo)出類型的參數(shù),通過(guò)export方法從客

77、戶端傳入 看看代碼吧,示例代碼如下: /* * 實(shí)現(xiàn)導(dǎo)出數(shù)據(jù)的業(yè)務(wù)功能對(duì)象 */public class ExportOperate     /*     * 導(dǎo)出文件     * param type 用戶選擇的導(dǎo)出類型     * param data 需要保存的數(shù)據(jù)     * return 是否成功導(dǎo)出文件     */ 

78、;   public boolean export(int type,String data)       /使用工廠方法       ExportFileApi api = factoryMethod(type);       return api.export(data);        /*    &#

79、160;* 工廠方法,創(chuàng)建導(dǎo)出的文件對(duì)象的接口對(duì)象     * param type 用戶選擇的導(dǎo)出類型     * return 導(dǎo)出的文件對(duì)象的接口對(duì)象     */    protected ExportFileApi factoryMethod(int type)      ExportFileApi api = null;    

80、0;  /根據(jù)類型來(lái)選擇究竟要?jiǎng)?chuàng)建哪一種導(dǎo)出文件對(duì)象        if(type=1)           api = new ExportTxtFile();       else if(type=2)           api = new Export

81、DB();              return api;     (4)此時(shí)的客戶端,非常簡(jiǎn)單,直接使用ExportOperate類,示例代碼如下: public class Client     public static void main(String args)         /創(chuàng)建需要使用的Creator對(duì)象 &

82、#160;     ExportOperate operate = new ExportOperate();       /調(diào)用輸出數(shù)據(jù)的功能方法,傳入選擇到處類型的參數(shù)        operate.export(1,"測(cè)試數(shù)據(jù)");     測(cè)試看看,然后修改一下客戶端的參數(shù),體會(huì)一下通過(guò)參數(shù)來(lái)選擇具體的導(dǎo)出實(shí)現(xiàn)的過(guò)程。這是一種很常見(jiàn)的參數(shù)化工廠方法的實(shí)現(xiàn)方式,但

83、是也還是有把參數(shù)化工廠方法實(shí)現(xiàn)成為抽象的,這點(diǎn)要注意,并不是說(shuō)參數(shù)化工廠方法就不能實(shí)現(xiàn)成為抽象類了。只是一般情況下,參數(shù)化工廠方法,在父類都會(huì)提供默認(rèn)的實(shí)現(xiàn)。(5)擴(kuò)展新的實(shí)現(xiàn)使用參數(shù)化工廠方法,擴(kuò)展起來(lái)會(huì)非常容易,已有的代碼都不會(huì)改變,只要新加入一個(gè)子類來(lái)提供新的工廠方法實(shí)現(xiàn),然后在客戶端使用這個(gè)新的子類即可。這種實(shí)現(xiàn)方式還有一個(gè)有意思的功能,就是子類可以選擇性覆蓋,不想覆蓋的功能還可以返回去讓父類來(lái)實(shí)現(xiàn),很有意思。先擴(kuò)展一個(gè)導(dǎo)出成xml文件的實(shí)現(xiàn),試試看,示例代碼如下: /* * 導(dǎo)出成xml文件的對(duì)象 */public class ExportXml imp

84、lements ExportFileApi    public boolean export(String data)        /簡(jiǎn)單示意一下       System.out.println("導(dǎo)出數(shù)據(jù)"+data+"到XML文件");        return true;     然后擴(kuò)展Expo

85、rtOperate類,來(lái)加入新的實(shí)現(xiàn),示例代碼如下: /* * 擴(kuò)展ExportOperate對(duì)象,加入可以導(dǎo)出XML文件 */public class ExportOperate2 extends ExportOperate    /*     * 覆蓋父類的工廠方法,創(chuàng)建導(dǎo)出的文件對(duì)象的接口對(duì)象     * param type 用戶選擇的導(dǎo)出類型     * return 導(dǎo)出的文件對(duì)象的接口對(duì)象     */    protected ExportFileA

溫馨提示

  • 1. 本站所有資源如無(wú)特殊說(shuō)明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁(yè)內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒(méi)有圖紙預(yù)覽就沒(méi)有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫(kù)網(wǎng)僅提供信息存儲(chǔ)空間,僅對(duì)用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對(duì)用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對(duì)任何下載內(nèi)容負(fù)責(zé)。
  • 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請(qǐng)與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對(duì)自己和他人造成任何形式的傷害或損失。

評(píng)論

0/150

提交評(píng)論