1. 程式人生 > >Java設計模式(二)之建立型模式:抽象工廠模式

Java設計模式(二)之建立型模式:抽象工廠模式

例子背景:

隨著客戶的要求越來越高,寶馬車需要不同配置的空調和發動機等配件。於是這個工廠開始生產空調和發動機,用來組裝汽車。這時候工廠有兩個系列的產品:空調和發動機。寶馬320系列配置A型號空調和A型號發動機,寶馬230系列配置B型號空調和B型號發動機。

 

一、概念:

在工廠方法模式中,我們使用一個工廠建立一個產品,也就是說一個具體的工廠對應一個具體的產品。但是有時候我們需要一個工廠能夠提供多個產品物件,而不是單一的物件,這個時候我們就需要使用抽象工廠模式。

在講解抽象工廠模式之前,我們需要釐清兩個概念:

(1)產品等級結構:產品的等級結構也就是產品的繼承結構。例如一個為空調的抽象類,它有海爾空調、格力空調、美的空調等一系列的子類,那麼這個抽象類空調和他的子類就構成了一個產品等級結構。

(2)產品族:產品族是在抽象工廠模式中的。在抽象工廠模式中,產品族是指由同一個工廠生產的,位於不同產品等級結構中的一組產品。比如,海爾工廠生產海爾空調。海爾冰箱,那麼海爾空調則位於空調產品族中。

產品等級結構和產品族結構示意圖如下:

 

二、基本定義:

抽象工廠模式提供一個介面,用於建立相關或者依賴物件的家族,而不需要明確指定具體類。抽象工廠允許使用抽象的介面來建立一組相關的產品,而不需要關心實際產出的具體產品是什麼,這樣一來,客戶就可以從具體的產品中被解耦。

如寶馬320系列使用空調型號A和發動機型號A,而寶馬230系列使用空調型號B和發動機型號B,那麼使用抽象工廠模式,在為320系列生產相關配件時,就無需制定配件的型號,它會自動根據車型生產對應的配件型號A。

UML結構圖如下:

AbstractFactory:抽象工廠。抽象工廠定義了一個介面,所有的具體工廠都必須實現此介面,這個介面包含了一組方法用來生產產品。

ConcreteFactory:具體工廠。具體工廠是用於生產不同產品族。要建立一個產品,客戶只需要使用其中一個工廠完全不需要例項化任何產品物件。

AbstractProduct:抽象產品。這是一個產品家族,每一個具體工廠都能夠生產一整組產品。

Product:具體產品。
 

三、程式碼:

結合本例如下:

當每個抽象產品都有多於一個的具體子類的時候(空調有型號A和B兩種,發動機也有型號A和B兩種),工廠角色怎麼知道例項化哪一個子類呢?比如每個抽象產品角色都有兩個具體產品(產品空調有兩個具體產品空調A和空調B)。抽象工廠模式提供兩個具體工廠角色(寶馬320系列工廠和寶馬230系列工廠),分別對應於這兩個具體產品角色,每一個具體工廠角色只負責某一個產品角色的例項化。每一個具體工廠類只負責建立抽象產品的某一個具體子類的例項。

產品類:

//發動機以及型號  
public interface Engine {  
 
}  
public class EngineA extends Engine{  
    public EngineA(){  
        System.out.println("製造-->EngineA");  
    }  
}  
public class EngineBextends Engine{  
    public EngineB(){  
        System.out.println("製造-->EngineB");  
    }  
}  
 
//空調以及型號  
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");  
    }  
} 

建立工廠類:

//建立工廠的介面  
public interface AbstractFactory {  
    //製造發動機
    public Engine createEngine();
    //製造空調 
    public Aircondition createAircondition(); 
}  
 
 
//為寶馬320系列生產配件  
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){  
        //生產寶馬320系列配件
        FactoryBMW320 factoryBMW320 = new FactoryBMW320();  
        factoryBMW320.createEngine();
        factoryBMW320.createAircondition();
          
        //生產寶馬523系列配件  
        FactoryBMW523 factoryBMW523 = new FactoryBMW523();  
        factoryBMW320.createEngine();
        factoryBMW320.createAircondition();
    }  
}

 

四、優缺點:

1、優點:

(1) 抽象工廠隔離了具體類的生成,是的客戶端不需要知道什麼被建立。所有的具體工廠都實現了抽象工廠中定義的公共介面,因此只需要改變具體工廠的例項,就可以在某種程度上改變整個軟體系統的行為。

(2)當一個產品族中的多個物件被設計成一起工作時,它能夠保證客戶端始終只使用同一個產品族中的物件。

2、缺點:

(1)新增新的行為時比較麻煩。如果需要新增一個新產品族物件時,需要更改介面及其下所有子類,這必然會帶來很大的麻煩。

 

五、使用場景:

(1)一個系統不應當依賴於產品類例項如何被建立、組合和表達的細節,這對於所有型別的工廠模式都是重要的。

(2)系統中有多於一個的產品族,而每次只使用其中某一產品族。

(3)屬於同一個產品族的產品將在一起使用,這一約束必須在系統的設計中體現出來。

(4)系統提供一個產品類的庫,所有的產品以同樣的接口出現,從而使客戶端不依賴於具體實現。
 

 

參考文章:

https://blog.csdn.net/jason0539/article/details/44976775

https://blog.csdn.net/chenssy/article/details/9010107