一区二区三区日韩精品-日韩经典一区二区三区-五月激情综合丁香婷婷-欧美精品中文字幕专区

分享

工廠模式我之見(jiàn)(簡(jiǎn)單工廠模式 VS 工廠方法模式)

 天落雨 2006-01-17
前言
工大有許多同學(xué)是做java的,大家都知道java最大的優(yōu)點(diǎn)是它的完全OO化和它在多年的發(fā)展過(guò)程中吸收和總結(jié)了許多先進(jìn)的框架與模式,其中工廠模式就是最常用的模式之一。下面我想將我在學(xué)習(xí)和實(shí)踐過(guò)程中對(duì)工廠模式的認(rèn)識(shí)與了解介紹給大家。由于筆者能力限制,在實(shí)踐中也沒(méi)參與過(guò)什么大的項(xiàng)目,筆者參與過(guò)的項(xiàng)目用到的工廠模式主要是簡(jiǎn)單工廠模式(Simple Factory)和工廠方法模式(Factory Method),所以筆者在本文主要介紹的是這兩種模式。



準(zhǔn)備知識(shí)
在OO設(shè)計(jì)領(lǐng)域,我們知道前人總結(jié)了不少的經(jīng)驗(yàn),許多的經(jīng)驗(yàn)在現(xiàn)代軟件工程過(guò)程中已經(jīng)被認(rèn)為是原則來(lái)遵守。下面筆者摘抄幾項(xiàng)下文涉及到的OO原則的定義。

OCP(開(kāi)閉原則,Open-Closed Principle):一個(gè)軟件的實(shí)體應(yīng)當(dāng)對(duì)擴(kuò)展開(kāi)放,對(duì)修改關(guān)閉。我的理解是,對(duì)于一個(gè)已有的軟件,如果需要擴(kuò)展,應(yīng)當(dāng)在不需修改已有代碼的基礎(chǔ)上進(jìn)行。

DIP(依賴倒轉(zhuǎn)原則,Dependence Inversion Principle):要針對(duì)接口編程,不要針對(duì)實(shí)現(xiàn)編程。我的理解是,對(duì)于不同層次的編程,高層次暴露給低層次的應(yīng)當(dāng)只是接口,而不是它的具體類。

LoD(迪米特法則,Law of Demeter):只與你直接的朋友通信,而避免和陌生人通信。眾所周知類(或模塊)之間的通信越少,耦合度就越低,從而更有利于我們對(duì)軟件的宏觀管理。老子論“圣人之治”有相同的思想,《老子》云:“是以圣人之治,虛其心,實(shí)其腹,弱其志,常使民無(wú)知無(wú)欲。”,又云:“小國(guó)寡民,鄰國(guó)相望,雞犬之聲相聞,民至老死,不相往來(lái)。”。佩服我們的老祖宗,N千年前就想到了西方N千年后才想到的東西,同時(shí)也佩服《java與模式》的作者閻宏,可以用中國(guó)傳統(tǒng)哲學(xué)思想這么生動(dòng)的說(shuō)明這一軟件設(shè)計(jì)原則。



簡(jiǎn)單工廠模式及實(shí)例
簡(jiǎn)單工廠模式又叫靜態(tài)工廠模式,顧名思義,它是用來(lái)實(shí)例化目標(biāo)類的靜態(tài)類。下面我主要通過(guò)一個(gè)簡(jiǎn)單的實(shí)例說(shuō)明簡(jiǎn)單工廠及其優(yōu)點(diǎn)。

比如有個(gè)國(guó)家的運(yùn)動(dòng)員協(xié)會(huì),他們是負(fù)責(zé)登記與注冊(cè)職業(yè)運(yùn)動(dòng)員的(就好像我們國(guó)家的體育總局,呵呵,無(wú)論足球籃球還是乒乓球的運(yùn)動(dòng)員都必須在這里注冊(cè)才能拿到我們國(guó)家職業(yè)運(yùn)動(dòng)員牌照)。一家體育俱樂(lè)部(比如籃球的廣東宏遠(yuǎn),足球的深圳健力寶)想獲得球員為自己俱樂(lè)部效力,就必須通過(guò)這個(gè)運(yùn)動(dòng)員協(xié)會(huì)。

根據(jù)DIP我們可以設(shè)計(jì)一個(gè)“運(yùn)動(dòng)員”接口,“足球運(yùn)動(dòng)員”和“籃球運(yùn)動(dòng)員”(還有其他運(yùn)動(dòng)員)都實(shí)現(xiàn)“運(yùn)動(dòng)員”這個(gè)接口。而“運(yùn)動(dòng)員協(xié)會(huì)”就是一個(gè)簡(jiǎn)單工廠類,它負(fù)責(zé)實(shí)例化“運(yùn)動(dòng)員”。我們這里的“俱樂(lè)部”就是一個(gè)客戶端(Client),不同的“俱樂(lè)部”就是不同的客戶端。具體如下圖表示:




對(duì)于不同的俱樂(lè)部對(duì)象(無(wú)論是八一還是深圳健力寶),他們都是面向“運(yùn)動(dòng)員”接口編程,而不用管是“足球運(yùn)動(dòng)員”還是“籃球運(yùn)動(dòng)員”,也就是說(shuō)實(shí)現(xiàn)了“運(yùn)動(dòng)員”接口的具體類“足球運(yùn)動(dòng)員”無(wú)需暴露給客戶端。這也滿足了DIP。但具體的俱樂(lè)部(比如足球的深圳健力寶)如何確保自己獲取的是自己想要的運(yùn)動(dòng)員(健力寶俱樂(lè)部需要的當(dāng)然是足球運(yùn)動(dòng)員)呢?這就需要“運(yùn)動(dòng)員協(xié)會(huì)”這一工廠類了。俱樂(lè)部通過(guò)調(diào)用“運(yùn)動(dòng)員協(xié)會(huì)”的具體方法,返回不同的實(shí)例。這同時(shí)也滿足了LoD,也就是“深圳健力寶足球俱樂(lè)部”對(duì)象不直接與“足球運(yùn)動(dòng)員:李毅”對(duì)象通信,而是通過(guò)他們共同的“朋友”——“國(guó)家體育總局”通信。

下面給出各個(gè)類的程序,會(huì)有助于讀者更好的了解筆者之前的介紹。

  Code: [Copy to clipboard]  
運(yùn)動(dòng)員.java
public interface 運(yùn)動(dòng)員 {       
        public void 跑();
        public void 跳();
}

足球運(yùn)動(dòng)員.java
public class 足球運(yùn)動(dòng)員 implements 運(yùn)動(dòng)員 {

        public void 跑(){
                //跑啊跑
        }
       
        public void 跳(){
                //跳啊跳
        }
}

籃球運(yùn)動(dòng)員.java
public class 籃球運(yùn)動(dòng)員 implements 運(yùn)動(dòng)員 {

        public void 跑(){
                //do nothing
        }
       
        public void 跳(){
                //do nothing
        }
}

體育協(xié)會(huì).java
public class 體育協(xié)會(huì) {
       
        public static 運(yùn)動(dòng)員 注冊(cè)足球運(yùn)動(dòng)員(){
                return new 足球運(yùn)動(dòng)員();
        }
       
        public static 運(yùn)動(dòng)員 注冊(cè)籃球運(yùn)動(dòng)員(){
                return new 籃球運(yùn)動(dòng)員();
        }

}

俱樂(lè)部.java
public class 俱樂(lè)部 {
        private 運(yùn)動(dòng)員 守門(mén)員;
        private 運(yùn)動(dòng)員 后衛(wèi);
        private 運(yùn)動(dòng)員 前鋒;

        public void test() {
                this.前鋒 = 體育協(xié)會(huì).注冊(cè)足球運(yùn)動(dòng)員();
                this.后衛(wèi) = 體育協(xié)會(huì).注冊(cè)足球運(yùn)動(dòng)員();
                this.守門(mén)員 = 體育協(xié)會(huì).注冊(cè)足球運(yùn)動(dòng)員();
               
                守門(mén)員.跑();
                后衛(wèi).跳();
        }
}

以上就是簡(jiǎn)單工廠模式的一個(gè)簡(jiǎn)單實(shí)例,讀者應(yīng)該想象不用接口不用工廠而把具體類暴露給客戶端的那種混亂情形吧(就好像沒(méi)了體育總局,各個(gè)俱樂(lè)部在市場(chǎng)上自己胡亂的尋找仔細(xì)需要的運(yùn)動(dòng)員),簡(jiǎn)單工廠就解決了這種混亂。

我們用OCP看看簡(jiǎn)單工廠,會(huì)發(fā)現(xiàn)如果要對(duì)系統(tǒng)進(jìn)行擴(kuò)展的話治需要增加實(shí)現(xiàn)產(chǎn)品接口的產(chǎn)品類(上例表現(xiàn)為“足球運(yùn)動(dòng)員”,“籃球運(yùn)動(dòng)員”類,比如要增加個(gè)“乒乓球運(yùn)動(dòng)員”類),而無(wú)需對(duì)原有的產(chǎn)品類進(jìn)行修改。這咋一看好像滿足OCP,但是實(shí)際上還是需要修改代碼的——對(duì),就是修改工廠類。上例中如果增加“乒乓球運(yùn)動(dòng)員”產(chǎn)品類,就必須相應(yīng)的修改“體育協(xié)會(huì)”工廠類,增加個(gè)“注冊(cè)乒乓球運(yùn)動(dòng)員”方法。所以可以看出,簡(jiǎn)單工廠模式是不滿足OCP的。



工廠方法模式及其實(shí)例
談了簡(jiǎn)單工廠模式,下面繼續(xù)談?wù)劰S方法模式。前一節(jié)的最末點(diǎn)明了簡(jiǎn)單工廠模式最大的缺點(diǎn)——不完全滿足OCP。為了解決這一缺點(diǎn),設(shè)計(jì)師們提出了工廠方法模式。工廠方法模式和簡(jiǎn)單工廠模式最大的不同在于,簡(jiǎn)單工廠模式只有一個(gè)(對(duì)于一個(gè)項(xiàng)目或者一個(gè)獨(dú)立模塊而言)工廠類,而工廠方法模式有一組實(shí)現(xiàn)了相同接口的工廠類。下面我們通過(guò)修改上一節(jié)的實(shí)例來(lái)介紹工廠方法模式。

我們?cè)诓桓淖儺a(chǎn)品類(“足球運(yùn)動(dòng)員”類和“籃球運(yùn)動(dòng)員”類)的情況下,修改下工廠類的結(jié)構(gòu),如下圖所示:




相關(guān)代碼如下:

  Code: [Copy to clipboard]  
運(yùn)動(dòng)員.java
public interface 運(yùn)動(dòng)員 {       
        public void 跑();
        public void 跳();
}

足球運(yùn)動(dòng)員.java
public class 足球運(yùn)動(dòng)員 implements 運(yùn)動(dòng)員 {

        public void 跑(){
                //跑啊跑
        }
       
        public void 跳(){
                //跳啊跳
        }
}

籃球運(yùn)動(dòng)員.java
public class 籃球運(yùn)動(dòng)員 implements 運(yùn)動(dòng)員 {

        public void 跑(){
                //do nothing
        }
       
        public void 跳(){
                //do nothing
        }
}

體育協(xié)會(huì).java
public interface 體育協(xié)會(huì) {
        public 運(yùn)動(dòng)員 注冊(cè)();
}

足球協(xié)會(huì).java
public class 足球協(xié)會(huì) implements 體育協(xié)會(huì) {
        public 運(yùn)動(dòng)員 注冊(cè)(){
                return new 足球運(yùn)動(dòng)員();
        }
}

籃球協(xié)會(huì).java
public class 籃球協(xié)會(huì) implements 體育協(xié)會(huì) {
        public 運(yùn)動(dòng)員 注冊(cè)(){
                return new 籃球運(yùn)動(dòng)員();
        }
}

俱樂(lè)部.java
public class 俱樂(lè)部 {
        private 運(yùn)動(dòng)員 守門(mén)員;
        private 運(yùn)動(dòng)員 后衛(wèi);
        private 運(yùn)動(dòng)員 前鋒;

        public void test() {
                體育協(xié)會(huì) 中國(guó)足協(xié) = new 足球協(xié)會(huì)();
               
                this.前鋒 = 中國(guó)足協(xié).注冊(cè)();
                this.后衛(wèi) = 中國(guó)足協(xié).注冊(cè)();

                守門(mén)員.跑();
                后衛(wèi).跳();
        }
}


很明顯可以看到,“體育協(xié)會(huì)”工廠類變成了“體育協(xié)會(huì)”接口,而實(shí)現(xiàn)此接口的分別是“足球協(xié)會(huì)”“籃球協(xié)會(huì)”等等具體的工廠類。

這樣做有什么好處呢?很明顯,這樣做就完全OCP了。如果需要再加入(或擴(kuò)展)產(chǎn)品類(比如加多個(gè)“乒乓球運(yùn)動(dòng)員”)的話就不再需要修改工廠類了,而只需相應(yīng)的再添加一個(gè)實(shí)現(xiàn)了工廠接口(“體育協(xié)會(huì)”接口)的具體工廠類。



簡(jiǎn)單工廠模式與工廠方法模式大PK
從以上對(duì)兩種模式的介紹可以了解到,工廠方法模式是為了克服簡(jiǎn)單工廠模式的缺點(diǎn)(主要是為了滿足OCP)而設(shè)計(jì)出來(lái)的。但是,工廠方法模式就一定比簡(jiǎn)單工廠模式好呢?筆者的答案是不一定。下面筆者將詳細(xì)比較兩種模式。

1. 結(jié)構(gòu)復(fù)雜度
從這個(gè)角度比較,顯然簡(jiǎn)單工廠模式要占優(yōu)。簡(jiǎn)單工廠模式只需一個(gè)工廠類,而工廠方法模式的工廠類隨著產(chǎn)品類個(gè)數(shù)增加而增加,這無(wú)疑會(huì)使類的個(gè)數(shù)越來(lái)越多,從而增加了結(jié)構(gòu)的復(fù)雜程度。

2.代碼復(fù)雜度
代碼復(fù)雜度和結(jié)構(gòu)復(fù)雜度是一對(duì)矛盾,既然簡(jiǎn)單工廠模式在結(jié)構(gòu)方面相對(duì)簡(jiǎn)潔,那么它在代碼方面肯定是比工廠方法模式復(fù)雜的了。簡(jiǎn)單工廠模式的工廠類隨著產(chǎn)品類的增加需要增加很多方法(或代碼),而工廠方法模式每個(gè)具體工廠類只完成單一任務(wù),代碼簡(jiǎn)潔。

3.客戶端編程難度
工廠方法模式雖然在工廠類結(jié)構(gòu)中引入了接口從而滿足了OCP,但是在客戶端編碼中需要對(duì)工廠類進(jìn)行實(shí)例化。而簡(jiǎn)單工廠模式的工廠類是個(gè)靜態(tài)類,在客戶端無(wú)需實(shí)例化,這無(wú)疑是個(gè)吸引人的優(yōu)點(diǎn)。

4.管理上的難度
這是個(gè)關(guān)鍵的問(wèn)題。
我們先談擴(kuò)展。眾所周知,工廠方法模式完全滿足OCP,即它有非常良好的擴(kuò)展性。那是否就說(shuō)明了簡(jiǎn)單工廠模式就沒(méi)有擴(kuò)展性呢?答案是否定的。簡(jiǎn)單工廠模式同樣具備良好的擴(kuò)展性——擴(kuò)展的時(shí)候僅需要修改少量的代碼(修改工廠類的代碼)就可以滿足擴(kuò)展性的要求了。盡管這沒(méi)有完全滿足OCP,但筆者認(rèn)為不需要太拘泥于設(shè)計(jì)理論,要知道,sun提供的java官方工具包中也有想到多沒(méi)有滿足OCP的例子啊(java.util.Calendar這個(gè)抽象類就不滿足OCP,具體原因大家可以分析下)。
然后我們從維護(hù)性的角度分析下。假如某個(gè)具體產(chǎn)品類需要進(jìn)行一定的修改,很可能需要修改對(duì)應(yīng)的工廠類。當(dāng)同時(shí)需要修改多個(gè)產(chǎn)品類的時(shí)候,對(duì)工廠類的修改會(huì)變得相當(dāng)麻煩(對(duì)號(hào)入座已經(jīng)是個(gè)問(wèn)題了)。反而簡(jiǎn)單工廠沒(méi)有這些麻煩,當(dāng)多個(gè)產(chǎn)品類需要修改是,簡(jiǎn)單工廠模式仍然僅僅需要修改唯一的工廠類(無(wú)論怎樣都能改到滿足要求吧?大不了把這個(gè)類重寫(xiě))。

由以上的分析,筆者認(rèn)為簡(jiǎn)單工廠模式更好用更方便些。當(dāng)然這只是筆者的個(gè)人看法而已,畢竟公認(rèn)的,工廠方法模式比簡(jiǎn)單工廠模式更“先進(jìn)”。但有時(shí)過(guò)于先進(jìn)的東西未必適合自己,這個(gè)見(jiàn)仁見(jiàn)智吧。


寫(xiě)在最后
本文僅討論了兩個(gè)常見(jiàn)的工廠模式,筆者很主觀的分析了各自的優(yōu)缺點(diǎn),這必定會(huì)引起許多異議。如果對(duì)筆者觀點(diǎn)有意見(jiàn)的,很歡迎跟貼批評(píng)指出。

其實(shí)究竟哪種模式更好,可能你會(huì)回答“都不好”,呵呵,別忘了,我們還有更“先進(jìn)”的“抽象工廠模式”。。。

最后交代下版權(quán)信息。本文許多定義性的內(nèi)容引用自《java與模式》(電子工業(yè)出版社,閻宏),這是本好書(shū),有時(shí)間有機(jī)會(huì)希望大家可以好好看看,我在此書(shū)中是獲益良多。另外筆者在寫(xiě)本文過(guò)程中還參考了《UML基礎(chǔ)、案例與應(yīng)用》(人民郵電出版社,Joseph Schmuller著,李虎、趙龍剛譯),除此外其余內(nèi)容均為原創(chuàng),轉(zhuǎn)貼請(qǐng)注明“工大后院版權(quán)所有”。

    本站是提供個(gè)人知識(shí)管理的網(wǎng)絡(luò)存儲(chǔ)空間,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點(diǎn)。請(qǐng)注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購(gòu)買(mǎi)等信息,謹(jǐn)防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請(qǐng)點(diǎn)擊一鍵舉報(bào)。
    轉(zhuǎn)藏 分享 獻(xiàn)花(0

    0條評(píng)論

    發(fā)表

    請(qǐng)遵守用戶 評(píng)論公約

    類似文章 更多

    欧美日韩亚洲国产精品| 中文字幕高清不卡一区| 久久热麻豆国产精品视频| 日韩一级毛一欧美一级乱| 欧美日韩最近中国黄片| 国产精品亚洲综合天堂夜夜| 黄片在线免费观看全集| 亚洲欧美日本国产有色| 婷婷伊人综合中文字幕| 丝袜人妻夜夜爽一区二区三区| 久久成人国产欧美精品一区二区 | 国产免费一区二区不卡| 日韩综合国产欧美一区| 亚洲国产香蕉视频在线观看| 欧美国产日韩在线综合| 天堂热东京热男人天堂| 国产成人综合亚洲欧美日韩| 国产激情一区二区三区不卡| 亚洲精品国男人在线视频| 91熟女大屁股偷偷对白| 中文字幕不卡欧美在线| 国产精品福利一二三区| 激情视频在线视频在线视频| 欧美成人高清在线播放| 好吊色欧美一区二区三区顽频 | 亚洲a码一区二区三区| 中文字幕日韩欧美理伦片| 最新日韩精品一推荐日韩精品| 熟女免费视频一区二区| 国语对白刺激高潮在线视频| 麻豆视频传媒入口在线看| 亚洲黄片在线免费小视频| 夫妻激情视频一区二区三区| 中文字幕乱码免费人妻av| 亚洲一区二区三区国产| 日韩欧美在线看一卡一卡| 国产一级性生活录像片| 少妇激情在线免费观看| 欧洲一级片一区二区三区| 果冻传媒精选麻豆白晶晶 | 精品视频一区二区不卡|