設(shè)計(jì)模式之Factory
發(fā)表時(shí)間:2024-05-31 來源:明輝站整理相關(guān)軟件相關(guān)文章人氣:
[摘要]定義:提供創(chuàng)建對(duì)象的接口.為何使用?工廠模式是我們最常用的模式了,著名的Jive論壇系統(tǒng),就大量使用了工廠模式.為什么說工廠模式是最常用,因?yàn)楣S模式就相當(dāng)于創(chuàng)建對(duì)象的new. 工廠模式就是用來創(chuàng)建對(duì)象的.比如我們有一個(gè)類Sample 我們要?jiǎng)?chuàng)建Sample的對(duì)象:Sample sample=ne...
定義:提供創(chuàng)建對(duì)象的接口.
為何使用?
工廠模式是我們最常用的模式了,著名的Jive論壇系統(tǒng),就大量使用了工廠模式.
為什么說工廠模式是最常用,因?yàn)楣S模式就相當(dāng)于創(chuàng)建對(duì)象的new. 工廠模式就是用來創(chuàng)建對(duì)象的.
比如我們有一個(gè)類Sample 我們要?jiǎng)?chuàng)建Sample的對(duì)象:
Sample sample=new Sample();
如果我們要在創(chuàng)建sample之前做點(diǎn)事情,比如,賦值等,可以使用Sample的構(gòu)造函數(shù):
Sample sample=new Sample(參數(shù));
如果創(chuàng)建sample時(shí)做的事情不是如賦值這樣簡單的事,可能是很長一段代碼,如果也寫入構(gòu)造函數(shù)中,那明顯的就違背了面向?qū)ο蟮脑瓌t.封裝(Encapsulation)和分派(Delegation);
我們需要將創(chuàng)建實(shí)例的責(zé)任與使用實(shí)例的責(zé)任分開, 使得語句
Sample sample=new Sample(參數(shù));
就是簡單的責(zé)任:使用Sample這個(gè)實(shí)例;至于創(chuàng)建Sample的任務(wù)就交給了Factory工廠模式.
還有,如果Sample有個(gè)繼承如MySample, 按照面向接口編程,我們需要將Sample抽象成一個(gè)接口.
現(xiàn)在Sample是接口,有兩個(gè)子類MySample 和HisSample .我們要實(shí)例化他們時(shí),如下:
Sample mysample=new MySample();
Sample hissample=new HisSample();
隨著項(xiàng)目的深入,Sample可能還會(huì)"生出很多兒子出來", 那么我們要對(duì)這些兒子一個(gè)個(gè)實(shí)例化,更糟糕的是,可能還要對(duì)以前的代碼進(jìn)行修改:加入后來生出兒子的實(shí)例.這在傳統(tǒng)程序中是無法避免的.
但如果你一開始就有意識(shí)使用了工廠模式,這些麻煩就沒有了.
你會(huì)建立一個(gè)專門生產(chǎn)Sample實(shí)例的工廠:
public class Factory{
public static Sample creator(){
....
if (which==1)
return new MySample();
else if (which==2)
return new HisSample();
}
}
那么在你的程序中,如果要實(shí)例化MySample時(shí).就使用
Sample sample=Factory.creator();
這樣,在整個(gè)就不涉及到Sample的具體子類,達(dá)到封裝效果,也就減少錯(cuò)誤修改的機(jī)會(huì),這個(gè)原理可以用很通俗的話來比喻:就是具體事情做得越多,越容易范錯(cuò)誤.這每個(gè)做過具體工作的人都深有體會(huì),相反,官做得越高,說出的話越抽象越籠統(tǒng),范錯(cuò)誤可能性就越少.好象我們從編程序中也能悟出人生道理?呵呵.
好了,言歸正傳,既然不可避免使用factory,那我們就認(rèn)識(shí)一下工廠模式.
如何使用?
工廠模式中有: 簡單工廠 工廠方法(Factory Method) 抽象工廠(Abstract Factory).
上例中,我們使用的是簡單工廠. 這幾個(gè)模式?jīng)]有很明顯的區(qū)別,在我的概念中,簡單工廠應(yīng)該是只有一個(gè)工廠方法,如果我們創(chuàng)建對(duì)象的方法變得復(fù)雜了,我們就可能要將上例中Factory變成抽象類,將共同部分封裝在抽象類中,不同部分使用子類實(shí)現(xiàn):
public abstract class Factory{
public abstract Sample creator();
public abstract Sample2 creator();
}
public class SimpleFactory extends Factory{
public Sample creator(){
......
}
public Sample2 creator(){
......
}
}
public class BombFactory extends Factory{
public Sample creator(){
......
}
public Sample2 creator(){
......
}
}
上例中我們只有一類產(chǎn)品接口 Sample , 工廠方法和抽象工廠可以創(chuàng)建多個(gè)產(chǎn)品接口的實(shí)例,比如Sample2 Sample3
FactoryMethod往往只是創(chuàng)建單個(gè)的實(shí)例。Abstract Factory創(chuàng)建一系列的實(shí)例組,這些實(shí)例彼此相關(guān)。
舉例1
下圖是抽象工廠圖:
在這張圖中, 有兩類產(chǎn)品接口interface RAM 和interface CPU; 同時(shí)有兩個(gè)創(chuàng)建方法:MacProducer和PCProducer,這兩個(gè)創(chuàng)建方法中都有createCPU()和createRAM(),返回的實(shí)例對(duì)象組是CPU和RAM, 這是分別來自兩類產(chǎn)品接口,表面彼此是相關(guān)的.因此它是抽象工廠.
舉例2
我們以Jive的ForumFactory為例:
public abstract class ForumFactory {
private static Object initLock = new Object();
private static String className = "com.jivesoftware.forum.database.DbForumFactory";
private static ForumFactory factory = null;
public static ForumFactory getInstance(Authorization authorization) {
//If no valid authorization passed in, return null.
if (authorization == null) {
return null;
}
//以下使用了Singleton 單態(tài)模式
if (factory == null) {
synchronized(initLock) {
if (factory == null) {
......
try {
//動(dòng)態(tài)轉(zhuǎn)載類
Class c = Class.forName(className);
factory = (ForumFactory)c.newInstance();
}
catch (Exception e) {
return null;
}
}
}
}
//Now, 返回 proxy.用來限制授權(quán)對(duì)forum的訪問
return new ForumFactoryProxy(authorization, factory,
factory.getPermissions(authorization));
}
//真正創(chuàng)建forum的方法由繼承forumfactory的子類去完成.
public abstract Forum createForum(String name, String description)
throws UnauthorizedException, ForumAlreadyExistsException;
....
}
因?yàn)楝F(xiàn)在的Jive是通過數(shù)據(jù)庫系統(tǒng)存放論壇帖子等內(nèi)容數(shù)據(jù),如果有人要擴(kuò)展為純粹的文件系統(tǒng)存放的論壇帖子,這個(gè)工廠方法ForumFactory就提供了提供動(dòng)態(tài)接口:
private static String className = "com.jivesoftware.forum.database.DbForumFactory";
你可以使用自己開發(fā)的創(chuàng)建forum的方法代替com.jivesoftware.forum.database.DbForumFactory就可以.
在上面的一段代碼中一共用了三種模式,除了工廠模式外,還有Singleton單態(tài)模式,以及proxy模式,proxy模式主要用來授權(quán)用戶對(duì)forum的訪問,因?yàn)樵L問forum有兩種人:一個(gè)是注冊用戶 一個(gè)是游客guest,那么那么相應(yīng)的權(quán)限就不一樣,而且這個(gè)權(quán)限是貫穿整個(gè)系統(tǒng)的,因此建立一個(gè)proxy,類似網(wǎng)關(guān)的概念,可以很好的達(dá)到這個(gè)效果.
好了.經(jīng)過上述簡單描述,你對(duì)工廠模式應(yīng)該有個(gè)簡單的印象,如果你要鉆研工廠模式,網(wǎng)絡(luò)上有很多英文資料,不過我覺得過分鉆研也沒有必要,主要是使用實(shí)踐,實(shí)際使用中工廠模式的變種很多,只要你知道這樣一個(gè)大概思路,相信在實(shí)踐中你會(huì)是工廠模式的設(shè)計(jì)創(chuàng)建高手!