王雅軒,頊 聰
(大連外國語學(xué)院 軟件學(xué)院,大連 116044)
Java對(duì)象的一般生產(chǎn)方法是用new來創(chuàng)建的,以類Sample為例,如果要?jiǎng)?chuàng)建類Sample的實(shí)例對(duì)象,只要使用下面的語句即可:
Sample sample=new Sample();
但是,通常在創(chuàng)建類sample的實(shí)例時(shí),要做些初始化的工作,比如賦值、查詢數(shù)據(jù)庫等。這好比工廠中的產(chǎn)品在真正出廠交付客戶之前,要做一些出廠設(shè)置或配置之類的工作。這時(shí)可以使用類Sample的有參構(gòu)造函數(shù),這樣生成實(shí)例就要寫成:
Sample sample=new Sample(參數(shù));
如果創(chuàng)建sample實(shí)例時(shí)所做的初始化工作不是像賦值這樣簡單的事,可能是很長一段代碼,如果也寫入構(gòu)造函數(shù)中,這有背于Java的面向?qū)ο蟮姆庋b和分割的思想,即盡量將長的代碼“切割”成每個(gè)小段,再將每個(gè)小段“封裝”起來。這樣,可以減少段與段之間的偶合性。以后如果需要修改,只要更改每個(gè)局部段即可,而不會(huì)對(duì)整體中的其他部分產(chǎn)生影響,即不會(huì)發(fā)生牽一發(fā),而動(dòng)全身的事情。
如果一個(gè)系統(tǒng)中存在的類較多,而且在編碼時(shí)不能預(yù)見需要?jiǎng)?chuàng)建哪一個(gè)類的實(shí)例,即需要根據(jù)一定的條件,來進(jìn)行選擇性地創(chuàng)建對(duì)象時(shí),用一般的生產(chǎn)方法實(shí)現(xiàn)起來也比較困難。
開發(fā)人員不希望創(chuàng)建了哪個(gè)類的實(shí)例以及如何創(chuàng)建實(shí)例的信息暴露給外部程序。
由于上述問題,我們需要將創(chuàng)建實(shí)例的工作與使用實(shí)例的工作分開, 也就是說,使創(chuàng)建實(shí)例所需要的大量初始化工作從類的構(gòu)造函數(shù)中分離出去,因此我們提出了工廠模式,在工廠模式中,我們就可以把這些復(fù)雜的初始化工作,或選擇性地生產(chǎn)產(chǎn)品的方法,或產(chǎn)品族的選擇都可以寫進(jìn)工廠中。
1)簡單工廠模式(Simple Factory)
簡單工廠模式又稱靜態(tài)工廠方法模式[1],它把大量具有共同接口的類的實(shí)例化的過程都封裝到了一個(gè)簡單工廠類里了。它實(shí)現(xiàn)了對(duì)象的創(chuàng)建的過程與客戶端的相互分離(即將創(chuàng)建對(duì)象的具體過程屏蔽隔離起來了),從而避免了客戶端與產(chǎn)品類的直接耦合關(guān)系。
2)多型工廠模式(Factory Method)
Factory Method是一種創(chuàng)建性模式,它定義了一個(gè)創(chuàng)建對(duì)象的接口,但是卻讓子類來決定具體實(shí)例化哪一個(gè)類.當(dāng)一個(gè)類無法預(yù)料要?jiǎng)?chuàng)建哪種類的對(duì)象或是一個(gè)類需要由子類來指定創(chuàng)建的對(duì)象時(shí)我們就需要用到Factory Method 模式了。簡單地說,F(xiàn)actory Method可以根據(jù)不同的條件產(chǎn)生不同的實(shí)例,當(dāng)然這些不同的實(shí)例通常是屬于相同的類型,具有共同的父類。Factory Method把創(chuàng)建這些實(shí)例的具體過程封裝起來了,簡化了客戶端的應(yīng)用,也改善了程序的擴(kuò)展性,使得將來可以做最小的改動(dòng)就可以加入新的待創(chuàng)建的類。
3)工具箱工廠模式(Abstract Factory)
抽象工廠模式是所有形態(tài)的工廠模式中最為抽象和最具一般性的一種形態(tài)。 抽象工廠模式是指當(dāng)有多個(gè)抽象角色時(shí),使用的一種工廠模式。抽象工廠模式可以向客戶端提供一個(gè)接口,使客戶端在不必指定產(chǎn)品的具體的情況下,創(chuàng)建多個(gè)產(chǎn)品族中的產(chǎn)品對(duì)象。
在簡單工廠模式中,一個(gè)工廠類處于對(duì)產(chǎn)品類實(shí)例化調(diào)用的中心位置上,它決定那一個(gè)產(chǎn)品類應(yīng)當(dāng)被實(shí)例化, 如同一個(gè)交通警察站在來往的車輛流中,決定放行那一個(gè)方向的車輛向那一個(gè)方向流動(dòng)一樣。
圖1 簡單工廠模式角色示意圖
從圖1我們可以看出簡單工廠模式涉及到工廠類角色、抽象產(chǎn)品角色、具體產(chǎn)品角色三個(gè)參與者。
1) 工廠類角色Creator:工廠類在客戶端的直接控制下(Create方法)創(chuàng)建產(chǎn)品對(duì)象
2)抽象產(chǎn)品角色Product:定義簡單工廠創(chuàng)建的對(duì)象的父類或它們共同擁有的接口??梢允且粋€(gè)類、抽象類或接口。
3) 具體產(chǎn)品角色ConcreteProduct:定義工廠具體加工出的對(duì)象。
工廠方法模式是簡單工廠模式的進(jìn)一步抽象化和推廣,工廠方法模式里不再只由一個(gè)工廠類決定那一個(gè)產(chǎn)品類應(yīng)當(dāng)被實(shí)例化,這個(gè)決定被交給子類去作[2,3]。
圖2 多型工廠模式角色示意圖
從圖2可以看出工廠方法模式涉及到抽象工廠角色、具體工廠角色、抽象產(chǎn)品角色和具體產(chǎn)品角色四個(gè)參與者。
1)抽象工廠角色:是工廠方法模式的核心,它負(fù)責(zé)定義創(chuàng)建抽象產(chǎn)品對(duì)象的工廠方法。抽象工廠不能被外界直接調(diào)用,但任何在模式中用于創(chuàng)建產(chǎn)品對(duì)象的工廠類都必須實(shí)現(xiàn)由它所定義的工廠方法。
2)具體工廠角色:是工廠方法模式的對(duì)外接口,它負(fù)責(zé)實(shí)現(xiàn)創(chuàng)建具體產(chǎn)品對(duì)象的內(nèi)部邏輯。具體工廠與應(yīng)用密切相關(guān),可以被外界直接調(diào)用,創(chuàng)建所需要的產(chǎn)品。
3)抽象產(chǎn)品角色:是工廠方法模式所創(chuàng)建的所有對(duì)象的父類,它負(fù)責(zé)描述所有具體產(chǎn)品共有的公共接口。
4)具體產(chǎn)品角色:是工廠方法模式的創(chuàng)建目標(biāo),所有創(chuàng)建的對(duì)象都是充當(dāng)這一角色的某個(gè)具體類的實(shí)例。
抽象工廠模式是所有形態(tài)的工廠模式中最為抽象和最具廣泛性的一種形態(tài),抽象工廠模式是工廠方法模式的進(jìn)一步擴(kuò)廣化和抽象化。
圖3 工具箱工廠模式角色示意圖
如圖3所示:當(dāng)有多個(gè)抽象產(chǎn)品角色時(shí),工廠方法模式已經(jīng)不能滿足要求。根據(jù)LSP里氏替換原則,任何接受父類型的地方,都應(yīng)當(dāng)能夠接受子類型[4]。因此,實(shí)際上系統(tǒng)所需要的,僅僅是類型與這些抽象產(chǎn)品角色相同的一些實(shí)例,而不是這些抽象產(chǎn)品的實(shí)例。換言之,也就是這些抽象產(chǎn)品的具體子類的實(shí)例。工廠類負(fù)責(zé)創(chuàng)建抽象產(chǎn)品的具體子類的實(shí)例。當(dāng)每個(gè)抽象產(chǎn)品都有多于一個(gè)的具體子類的時(shí)候,工廠角色怎么知道實(shí)例化哪一個(gè)子類呢?比如每個(gè)抽象產(chǎn)品角色都有兩個(gè)具體產(chǎn)品。抽象工廠模式提供兩個(gè)具體工廠角色,分別對(duì)應(yīng)于這兩個(gè)具體產(chǎn)品角色,每一個(gè)具體工廠角色只負(fù)責(zé)某一個(gè)產(chǎn)品角色的實(shí)例化。每一個(gè)具體工廠類只負(fù)責(zé)創(chuàng)建抽象產(chǎn)品的某一個(gè)具體子類的實(shí)例。
工廠方法模式和簡單工廠模式在定義上的不同是很明顯的。工廠方法模式的核心是一個(gè)抽象工廠類,而不像簡單工廠模式, 把核心放在一個(gè)實(shí)類上。工廠方法模式可以允許很多實(shí)的工廠類從抽象工廠類繼承下來, 從而可以在實(shí)際上成為多個(gè)簡單工廠模式的綜合,從而推廣了簡單工廠模式。
反過來講,簡單工廠模式是由工廠方法模式退化而來。設(shè)想如果我們非常確定一個(gè)系統(tǒng)只需要一個(gè)實(shí)際工廠類, 那么就不妨把抽象工廠類合并到實(shí)的工廠類中去。而這樣一來,我們就退化到簡單工廠模式了。
而在抽象工廠模式中,抽象產(chǎn)品可能是一個(gè)或多個(gè),從而構(gòu)成一個(gè)或多個(gè)產(chǎn)品族。 在只有一個(gè)產(chǎn)品族的情況下,抽象工廠模式實(shí)際上退化到工廠方法模式。
工廠方法為系統(tǒng)結(jié)構(gòu)提供了非常靈活強(qiáng)大的動(dòng)態(tài)擴(kuò)展機(jī)制,在需要的時(shí)候,只要更換一下具體的工廠方法,系統(tǒng)其他地方無需任何變換,就有可能將系統(tǒng)功能進(jìn)行改頭換面的變化。
簡單工廠模式是由一個(gè)具體的類去創(chuàng)建其他類的實(shí)例,父類是相同的,父類是具體的。
工廠方法模式是有一個(gè)抽象的父類定義公共接口,子類負(fù)責(zé)生成具體的對(duì)象,這樣做的目的是將類的實(shí)例化操作延遲到子類中完成。
抽象工廠模式提供一個(gè)創(chuàng)建一系列相關(guān)或相互依賴對(duì)象的接口,而無須指定他們具體的類。它針對(duì)的是有多個(gè)產(chǎn)品的等級(jí)結(jié)構(gòu)。而工廠方法模式針對(duì)的是一個(gè)產(chǎn)品的等級(jí)結(jié)構(gòu)。
[1] Steven Metsker, William C.Wake 著,龔波,趙彩琳,陳蓓譯.Java設(shè)計(jì)模式[M].北京:人民郵電出版社.2007.
[2] 閻宏.Java與模式[M]. 北京:電子工業(yè)出版社.2002.
[3] 結(jié)城浩.博碩文化譯.設(shè)計(jì)模式- Java語言中的應(yīng)用[M].北京: 中國鐵道出版社, 2005.
[4] James W.Cooper 著.王宇,杜琪,杜志秀,譯.Java與設(shè)計(jì)模式[M].北京:中國電力出版社.2003.