Java設(shè)計(jì)模式—工廠模式

一、工廠模式簡(jiǎn)介

意圖
定義一個(gè)創(chuàng)建對(duì)象的接口,讓其子類自己決定實(shí)例化哪一個(gè)工廠類,工廠模式使其創(chuàng)建過(guò)程延遲到子類進(jìn)行。
主要解決
主要解決接口選擇的問(wèn)題。
何時(shí)使用
我們明確地計(jì)劃不同條件下創(chuàng)建不同實(shí)例時(shí)。
如何解決
讓其子類實(shí)現(xiàn)工廠接口,返回的也是一個(gè)抽象的產(chǎn)品。
關(guān)鍵代碼
創(chuàng)建過(guò)程在其子類執(zhí)行。
優(yōu)點(diǎn)
1、一個(gè)調(diào)用者想創(chuàng)建一個(gè)對(duì)象,只要知道其名稱就可以了。
2、擴(kuò)展性高,如果想增加一個(gè)產(chǎn)品,只要擴(kuò)展一個(gè)工廠類就可以。
3、屏蔽產(chǎn)品的具體實(shí)現(xiàn),調(diào)用者只關(guān)心產(chǎn)品的接口。
缺點(diǎn)
每次增加一個(gè)產(chǎn)品時(shí),都需要增加一個(gè)具體類和對(duì)象實(shí)現(xiàn)工廠,使得系統(tǒng)中類的個(gè)數(shù)成倍增加,在一定程度上增加了系統(tǒng)的復(fù)雜度,同時(shí)也增加了系統(tǒng)具體類的依賴。這并不是什么好事。
注意事項(xiàng)
作為一種創(chuàng)建類模式,在任何需要生成復(fù)雜對(duì)象的地方,都可以使用工廠方法模式。有一點(diǎn)需要注意的地方就是復(fù)雜對(duì)象適合使用工廠模式,而簡(jiǎn)單對(duì)象,特別是只需要通過(guò) new 就可以完成創(chuàng)建的對(duì)象,無(wú)需使用工廠模式。如果使用工廠模式,就需要引入一個(gè)工廠類,會(huì)增加系統(tǒng)的復(fù)雜度。

二、分類

工廠模式主要是為創(chuàng)建對(duì)象提供過(guò)渡接口,以便將創(chuàng)建對(duì)象的具體過(guò)程屏蔽隔離起來(lái),達(dá)到提高靈活性的目的。

工廠模式可以分為三類:
1)簡(jiǎn)單工廠模式(Simple Factory)
2)工廠方法模式(Factory Method)
3)抽象工廠模式(Abstract Factory)
這三種模式從上到下逐步抽象,并且更具一般性。
GOF在《設(shè)計(jì)模式》一書(shū)中將工廠模式分為兩類:工廠方法模式(Factory Method)與抽象工廠模式(Abstract Factory)。
將簡(jiǎn)單工廠模式(Simple Factory)看為工廠方法模式的一種特例,兩者歸為一類。

三、區(qū)別

工廠方法模式:
一個(gè)抽象產(chǎn)品類,可以派生出多個(gè)具體產(chǎn)品類。
一個(gè)抽象工廠類,可以派生出多個(gè)具體工廠類。
每個(gè)具體工廠類只能創(chuàng)建一個(gè)具體產(chǎn)品類的實(shí)例。
抽象工廠模式:
多個(gè)抽象產(chǎn)品類,每個(gè)抽象產(chǎn)品類可以派生出多個(gè)具體產(chǎn)品類。
一個(gè)抽象工廠類,可以派生出多個(gè)具體工廠類。
每個(gè)具體工廠類可以創(chuàng)建多個(gè)具體產(chǎn)品類的實(shí)例。
區(qū)別:
工廠方法模式只有一個(gè)抽象產(chǎn)品類,而抽象工廠模式有多個(gè)。
工廠方法模式的具體工廠類只能創(chuàng)建一個(gè)具體產(chǎn)品類的實(shí)例,而抽象工廠模式可以創(chuàng)建多個(gè)。
兩者皆可。

四、簡(jiǎn)單工廠模式

引子
假如有位客戶需要擁有寶馬車,于是他自己動(dòng)手創(chuàng)造了幾輛。

創(chuàng)建寶馬.png

public class BMW320 {  
    public BMW320(){  
        System.out.println("制造-->BMW320");  
    }  
}  
  
public class BMW523 {  
    public BMW523(){  
        System.out.println("制造-->BMW523");  
    }  
}  
  
public class Customer {  
    public static void main(String[] args) {  
        BMW320 bmw320 = new BMW320();  
        BMW523 bmw523 = new BMW523();  
    }  
}  

簡(jiǎn)單工廠模式又稱靜態(tài)工廠方法模式。重命名上就可以看出這個(gè)模式一定很簡(jiǎn)單。它存在的目的很簡(jiǎn)單:定義一個(gè)用于創(chuàng)建對(duì)象的接口。
先來(lái)看看它的組成:
1) 工廠類角色:這是本模式的核心,含有一定的商業(yè)邏輯和判斷邏輯,用來(lái)創(chuàng)建產(chǎn)品
2) 抽象產(chǎn)品角色:它一般是具體產(chǎn)品繼承的父類或者實(shí)現(xiàn)的接口。
3) 具體產(chǎn)品角色:工廠類所創(chuàng)建的對(duì)象就是此角色的實(shí)例。在java中由一個(gè)具體類實(shí)現(xiàn)。
但是這種情況必須要求客戶自己具有造車的能力,客戶和車就緊緊耦合在一起了。為了解決這個(gè)問(wèn)題,客戶可以把造車的具體任務(wù)委派給一個(gè)工廠來(lái)完成,而客戶只需要委托工廠創(chuàng)造自己喜歡的型號(hào)就行了。
我們建立一個(gè)簡(jiǎn)單工廠來(lái)幫助客戶造車:

簡(jiǎn)單工廠模式 UML圖.png

產(chǎn)品類

abstract class BMW {  
    public BMW(){  
          
    }  
}  
  
public class BMW320 extends BMW {  
    public BMW320() {  
        System.out.println("制造-->BMW320");  
    }  
}  
public class BMW523 extends BMW{  
    public BMW523(){  
        System.out.println("制造-->BMW523");  
    }  
} 

工廠類

public class Factory {  
    public BMW createBMW(int type) {  
        switch (type) {  
          
        case 320:  
            return new BMW320();  
  
        case 523:  
            return new BMW523();  
  
        default:  
            break;  
        }  
        return null;  
    }  
}  

客戶類

public class Customer {  
    public static void main(String[] args) {  
        Factory factory = new Factory();  
        BMW bmw320 = factory.createBMW(320);  
        BMW bmw523 = factory.createBMW(523);  
    }  
}  

這確實(shí)能在一定程度上滿足用戶的需求,但是假如用戶以后又有了新的需求,想要一種新型寶馬車,我們只能在工廠類中增加相應(yīng)的創(chuàng)建業(yè)務(wù)邏輯(createBMW(int type)方法需要新增case),這顯然是違背開(kāi)閉原則的??上攵獙?duì)于新產(chǎn)品的加入,工廠類是很被動(dòng)的。對(duì)于這樣的工廠類,我們稱它為全能類或者上帝類。
此時(shí)工廠方法模式應(yīng)運(yùn)而生。

五、工廠方法模式

工廠方法模式去掉了簡(jiǎn)單工廠模式中工廠方法的靜態(tài)屬性,使得它可以被子類繼承。這樣在簡(jiǎn)單工廠模式里集中在工廠方法上的壓力可以由工廠方法模式里不同的工廠子類來(lái)分擔(dān)。
工廠方法模式組成:
1)抽象工廠角色: 這是工廠方法模式的核心,它與應(yīng)用程序無(wú)關(guān)。是具體工廠角色必須實(shí)現(xiàn)的接口或者必須繼承的父類。在java中它由抽象類或者接口來(lái)實(shí)現(xiàn)。
2)具體工廠角色:它含有和具體業(yè)務(wù)邏輯有關(guān)的代碼。由應(yīng)用程序調(diào)用以創(chuàng)建對(duì)應(yīng)的具體產(chǎn)品的對(duì)象。
3)抽象產(chǎn)品角色:它是具體產(chǎn)品繼承的父類或者是實(shí)現(xiàn)的接口。在java中一般有抽象類或者接口來(lái)實(shí)現(xiàn)。
4)具體產(chǎn)品角色:具體工廠角色所創(chuàng)建的對(duì)象就是此角色的實(shí)例。在java中由具體的類來(lái)實(shí)現(xiàn)。
產(chǎn)品類

abstract class BMW {  
    public BMW(){  
          
    }  
}  
public class BMW320 extends BMW {  
    public BMW320() {  
        System.out.println("制造-->BMW320");  
    }  
}  
public class BMW523 extends BMW{  
    public BMW523(){  
        System.out.println("制造-->BMW523");  
    }  
}  

創(chuàng)建工廠類

interface FactoryBMW {  
    BMW createBMW();  
}  
  
public class FactoryBMW320 implements FactoryBMW{  
  
    @Override  
    public BMW320 createBMW() {  
  
        return new BMW320();  
    }  
  
}  
public class FactoryBMW523 implements FactoryBMW {  
    @Override  
    public BMW523 createBMW() {  
  
        return new BMW523();  
    }  
}  

客戶類

public class Customer {  
    public static void main(String[] args) {  
        FactoryBMW320 factoryBMW320 = new FactoryBMW320();  
        BMW320 bmw320 = factoryBMW320.createBMW();  
  
        FactoryBMW523 factoryBMW523 = new FactoryBMW523();  
        BMW523 bmw523 = factoryBMW523.createBMW();  
    }  
}  

工廠方法模式仿佛已經(jīng)很完美的對(duì)對(duì)象的創(chuàng)建進(jìn)行了包裝,使得客戶程序中僅僅處理抽象產(chǎn)品角色提供的接口,但使得對(duì)象的數(shù)量成倍增長(zhǎng)。當(dāng)產(chǎn)品種類非常多時(shí),會(huì)出現(xiàn)大量的與之對(duì)應(yīng)的工廠對(duì)象,這不是我們所希望的。
隨著客戶的要求越來(lái)越高,寶馬車需要不同配置的空調(diào)和發(fā)動(dòng)機(jī)等配件。于是這個(gè)工廠開(kāi)始生產(chǎn)空調(diào)和發(fā)動(dòng)機(jī),用來(lái)組裝汽車。這時(shí)候工廠有兩個(gè)系列的產(chǎn)品:空調(diào)和發(fā)動(dòng)機(jī)。寶馬320系列配置A型號(hào)空調(diào)和A型號(hào)發(fā)動(dòng)機(jī),寶馬230系列配置B型號(hào)空調(diào)和B型號(hào)發(fā)動(dòng)機(jī)。

六、抽象工廠模式

概念:
抽象工廠模式是工廠方法模式的升級(jí)版本,他用來(lái)創(chuàng)建一組相關(guān)或者相互依賴的對(duì)象。比如寶馬320系列使用空調(diào)型號(hào)A和發(fā)動(dòng)機(jī)型號(hào)A,而寶馬230系列使用空調(diào)型號(hào)B和發(fā)動(dòng)機(jī)型號(hào)B,那么使用抽象工廠模式,在為320系列生產(chǎn)相關(guān)配件時(shí),就無(wú)需制定配件的型號(hào),它會(huì)自動(dòng)根據(jù)車型生產(chǎn)對(duì)應(yīng)的配件型號(hào)A。

當(dāng)每個(gè)抽象產(chǎn)品都有多于一個(gè)的具體子類的時(shí)候(空調(diào)有型號(hào)A和B兩種,發(fā)動(dòng)機(jī)也有型號(hào)A和B兩種),工廠角色怎么知道實(shí)例化哪一個(gè)子類呢?比如每個(gè)抽象產(chǎn)品角色都有兩個(gè)具體產(chǎn)品(產(chǎn)品空調(diào)有兩個(gè)具體產(chǎn)品空調(diào)A和空調(diào)B)。抽象工廠模式提供兩個(gè)具體工廠角色(寶馬320系列工廠和寶馬230系列工廠),分別對(duì)應(yīng)于這兩個(gè)具體產(chǎn)品角色,每一個(gè)具體工廠角色只負(fù)責(zé)某一個(gè)產(chǎn)品角色的實(shí)例化。每一個(gè)具體工廠類只負(fù)責(zé)創(chuàng)建抽象產(chǎn)品的某一個(gè)具體子類的實(shí)例。

產(chǎn)品類

//發(fā)動(dòng)機(jī)以及型號(hào)    
public interface Engine {    
  
}    
public class EngineA extends Engine{    
    public EngineA(){    
        System.out.println("制造-->EngineA");    
    }    
}    
public class EngineBextends Engine{    
    public EngineB(){    
        System.out.println("制造-->EngineB");    
    }    
}    
  
//空調(diào)以及型號(hào)    
public interface Aircondition {    
  
}    
public class AirconditionA extends Aircondition{    
    public AirconditionA(){    
        System.out.println("制造-->AirconditionA");    
    }    
}    
public class AirconditionB extends Aircondition{    
    public AirconditionB(){    
        System.out.println("制造-->AirconditionB");    
    }    
}   

創(chuàng)建工廠類

//創(chuàng)建工廠的接口    
public interface AbstractFactory {    
    //制造發(fā)動(dòng)機(jī)  
    public Engine createEngine();  
    //制造空調(diào)   
    public Aircondition createAircondition();   
}    
  
  
//為寶馬320系列生產(chǎn)配件    
public class FactoryBMW320 implements AbstractFactory{    
        
    @Override    
    public Engine createEngine() {      
        return new EngineA();    
    }    
    @Override    
    public Aircondition createAircondition() {    
        return new AirconditionA();    
    }    
}    
//寶馬523系列  
public class FactoryBMW523 implements AbstractFactory {    
    
     @Override    
    public Engine createEngine() {      
        return new EngineB();    
    }    
    @Override    
    public Aircondition createAircondition() {    
        return new AirconditionB();    
    }    
  
  
}   

客戶類

public class Customer {    
    public static void main(String[] args){    
        //生產(chǎn)寶馬320系列配件  
        FactoryBMW320 factoryBMW320 = new FactoryBMW320();    
        factoryBMW320.createEngine();  
        factoryBMW320.createAircondition();  
            
        //生產(chǎn)寶馬523系列配件    
        FactoryBMW523 factoryBMW523 = new FactoryBMW523();    
        factoryBMW320.createEngine();  
        factoryBMW320.createAircondition();  
    }    
} 

好了,工廠模式基本上就這些內(nèi)容了。工廠模式確實(shí)為系統(tǒng)結(jié)構(gòu)提供了非常靈活強(qiáng)大的動(dòng)態(tài)擴(kuò)展機(jī)制,只要我們更換一下具體的工廠方法,系統(tǒng)其他地方無(wú)需一點(diǎn)變換,就有可能將系統(tǒng)功能進(jìn)行改頭換面的變化。
多看幾遍例子,自己敲幾遍運(yùn)行一下慢慢就會(huì)理解了。


參考鏈接
http://www.runoob.com/design-pattern/factory-pattern.html
http://blog.csdn.net/hguisu/article/details/7505909
http://blog.csdn.net/jason0539/article/details/23020989

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 一、工廠模式主要是為創(chuàng)建對(duì)象提供過(guò)渡接口,以便將創(chuàng)建對(duì)象的具體過(guò)程屏蔽隔離起來(lái),達(dá)到提高靈活性的目的。 工廠模式在...
    逆風(fēng)飛行1226閱讀 651評(píng)論 0 0
  • 在java中,通常使用new操作符創(chuàng)建對(duì)象的實(shí)例。但是在一些情況下,new操作符直接生成對(duì)象會(huì)帶來(lái)一些問(wèn)題,例如:...
    步積閱讀 961評(píng)論 2 3
  • 設(shè)計(jì)模式匯總 一、基礎(chǔ)知識(shí) 1. 設(shè)計(jì)模式概述 定義:設(shè)計(jì)模式(Design Pattern)是一套被反復(fù)使用、多...
    MinoyJet閱讀 4,094評(píng)論 1 15
  • 對(duì)于輸入樣本Tensor X來(lái)說(shuō),PCA一般不會(huì)直接對(duì)X進(jìn)行特征值分解,因?yàn)閄往往不能保證是實(shí)對(duì)稱方陣。所以PCA...
    對(duì)抗天網(wǎng)的小人兒閱讀 691評(píng)論 0 0
  • 若想對(duì)真理有完整透徹的體悟,必須懂得如何「吸入」和反映它?!干竦膰?guó)」真正指的是重新整合的意識(shí),也可比喻為重生或復(fù)原...
    Vicky靈氣閱讀 379評(píng)論 0 0

友情鏈接更多精彩內(nèi)容