Java工廠模式的深入瞭解

一、簡單工廠模式

何為簡單工廠模式?

首先先通過一個案例來理解

我有一個需求,要買車,買車有不同的型號,那麼我們常見的做法就是我買車點有什麼車我就買什麼車,實例如下

定義一個車接口

 
public interface Car {
    void name();
}

定義一個實現類,例如寶馬

public class Baoma implements Car {
 
    @Override
    public void name() {
        System.out.println("寶馬");
    }
}

測試

public class Test {
    public static void main(String[] args) {
        
        Car car3 = new Baoma();
        car3.name();

 結果:寶馬

很顯然這並不符合我們工廠設計模式的思想,我們不應該讓用戶去new一個車出來,現實生活中也不可能自己去new一個車然後自己買,對不對,因此我們要設計一個簡單的工廠來滿足我們的需求,

簡單工廠類

public class CarFactory {
    public static Car getCar(String car) {
        if(car.equals("寶馬")) {
            return new Baoma();
        }else if(car.equals("奧迪")) {
            return new AoDI();
        }
        return null;
    }
}

測試

 Car car = CarFactory.getCar("寶馬");
        car.name();
 
        Car car1 = CarFactory.getCar("奧迪");
        car1.name();

結果:寶馬 奧迪

那麼此時我們用戶就不需要去關心我們的車是怎麼來的,車該怎麼造出來,造出來是什麼車,我用戶隻管從工廠中去拿出我們需要的車即可,如果沒有,再從工廠中去添加

 

        

該圖是對簡單工廠模式的一個輔助理解。     

總結一下,簡單工廠模式: 用來生產同一等級結構中的任意產品(對於增加新的產品,需要覆蓋已有代碼)                  

二、工廠方法模式

那麼在簡單工廠類大傢應該發現瞭一個問題,如果我們需要添加一輛新車,就需要進入工廠修改工廠的代碼,如果我們修改瞭我們的代碼,那麼久違反瞭我們設計模式的開閉原則,不好,那麼我們就來到瞭我們的工廠方法模式。

何為工廠方法模式,示例如下:

其中車類和車接口不變,我們改變一下車工廠

我們定義一個車接口,方法返回一輛車

public interface CarFactory {
    Car getCar();
}

那麼我們可以想就是給每個車都配一個車工廠,那麼添加的時候,隻需要在新添加一個車工廠,去實現這個車工廠接口即可

奧迪工廠

public class AoDIFactory implements CarFactory{
 
    @Override
    public Car getCar() {
        return new AoDI();
    }
}

寶馬工廠我就不演示瞭。

測試

        Car baoma = new BaoMaFactory().getCar();
        Car Aodi = new AoDIFactory().getCar();
 
        baoma.name();
        Aodi.name();

 

那麼此時如果我們要添加新車,我們隻需要去添加他的車以及他的工廠即可,用戶則隻需要去找對應的工廠

 

總結一下,

工廠方法模式:用來生產同一等級結構中的固定產品(支持增加任意產品)

三、抽象工廠模式

前面介紹的工廠方法模式中考慮的是一類產品的生產,如畜牧場隻養動物、電視機廠隻生產電視機、計算機軟件學院隻培養計算機軟件專業的學生等。

同種類稱為同等級,也就是說:工廠方法模式中隻考慮生產同等級的產品,但是在現實生活中許多工廠是綜合型的工廠,能生產多等級(種類) 的產品,如農場裡既養動物又種植物,電器廠既生產電視機又生產洗衣機或空調,大學既有軟件專業又有生物專業等。

這裡需要先瞭解一個定義:

產品族:將同一個具體工廠所生產的位於不同等級的一組產品稱為一個產品族

如圖所示

3.1、抽象工廠模式的定義

是一種為訪問類提供一個創建一組相關或相互依賴對象接口,且訪問類無須指定所要產品的具體類就能得到同族的不同等級的產品的模式結構。

使用抽象工廠模式一般要滿足以下條件

可以在類的內部對產品族中相關聯的多等級產品共同管理,而不必專門引入多個新的類來進行管理。
當需要產品族時,抽象工廠可以保證客戶端始終隻使用同一個產品的產品組
抽象工廠增強瞭程序的可擴展性,當增加一個新的產品族時,不需要修改原代碼,滿足開閉原則。

當然使用抽象工廠模式也是有缺點的:        

當產品族中需要增加一個新的產品時,所有的工廠類都需要進行修改。增加瞭系統的抽象性和理解難度。

3.2、  抽象工廠模式的結構

1. 抽象工廠(Abstract Factory):提供瞭創建產品的接口,它包含多個創建產品的方法 newProduct(),可以創建多個不同等級的產品。

2. 具體工廠(Concrete Factory):主要是實現抽象工廠中的多個抽象方法,完成具體產品的創建。

3. 抽象產品(Product):定義瞭產品的規范,描述瞭產品的主要特性和功能,抽象工廠模式有多個抽象產品。

4. 具體產品(ConcreteProduct):實現瞭抽象產品角色所定義的接口,由具體工廠來創建,它同具體工廠之間是多對一的關系。

3.3抽象工廠模式代碼示例

首先我們去定義抽象產品

比如

 * @Description 車接口
 */
public interface Car {
    void startCar();
    void stopCar();
    void washCar();
}
 * @Description 車載音響類
 */
public interface CarAudio {
    void startCarAudio();
    void stopCarAudio();
}

提供具體的產品

 * @Description 奧迪車
 */
public class AodiCar implements Car {
    @Override
    public void startCar() {
        System.out.println("啟動奧迪車");
    }
 
    @Override
    public void stopCar() {
        System.out.println("關閉奧迪車");
    }
 
    @Override
    public void washCar() {
        System.out.println("洗奧迪車");
    }
}
 * @Description 奧迪車載音響
 */
public class AodiCarAudio implements CarAudio{
 
    @Override
    public void startCarAudio() {
        System.out.println("開啟奧迪車載音響");
    }
 
    @Override
    public void stopCarAudio() {
        System.out.println("關閉奧迪車載音響");
    }
}
 * @Description 寶馬車
 */
public class BaomaCar implements Car{
    @Override
    public void startCar() {
        System.out.println("開啟寶馬");
    }
 
    @Override
    public void stopCar() {
        System.out.println("停下寶馬");
    }
 
    @Override
    public void washCar() {
        System.out.println("洗寶馬");
    }
}
 * @Description 寶馬車載音響
 */
public class BaomaCarAudio implements CarAudio{
    @Override
    public void startCarAudio() {
        System.out.println("打開寶馬車載音響");
    }
 
    @Override
    public void stopCarAudio() {
        System.out.println("關閉寶馬車載音響");
    }
}

提供抽象的工廠

 * @Description 產品工廠接口
 */
public interface ProductFactory {
    Car ProductCar();
    CarAudio ProductCarAudio();
}

提供具體的工廠

 * @Description 寶馬工廠
 */
public class BaomaFactory implements ProductFactory{
 
    @Override
    public Car ProductCar() {
        return new BaomaCar();
    }
 
    @Override
    public CarAudio ProductCarAudio() {
        return new BaomaCarAudio();
    }
}
 * @Description aodi工廠
 */
public class AodiFactory implements ProductFactory{
    @Override
    public Car ProductCar() {
        return new AodiCar();
    }
 
    @Override
    public CarAudio ProductCarAudio() {
        return new AodiCarAudio();
    }
}

客戶測試類

 * @Description 消費者類
 */
public class Customer {
    public static void main(String[] args) {
        System.out.println("--------奧迪系列---------");
        //獲得奧迪工廠
        AodiFactory aodiFactory = new AodiFactory();
        Car car = aodiFactory.ProductCar();
        CarAudio carAudio = aodiFactory.ProductCarAudio();
        car.startCar();
        car.stopCar();
        carAudio.startCarAudio();
 
 
        System.out.println("--------寶馬系列---------");
 
        BaomaFactory baomaFactory = new BaomaFactory();
        Car carBaoma = baomaFactory.ProductCar();
        CarAudio carAudioBaoma = baomaFactory.ProductCarAudio();
        carBaoma.stopCar();
        carBaoma.washCar();
        carAudioBaoma.startCarAudio();
 
    }
}

輸出結果

        ——–奧迪系列———
啟動奧迪車
關閉奧迪車
開啟奧迪車載音響
——–寶馬系列———
停下寶馬
洗寶馬
打開寶馬車載音響

idea中類圖關系

如果我們要新增產品,需在總工廠去添加方法,而且其他的類也會修改,印證瞭我們之前寫到的缺點,

總結一下:

抽象工廠模式就是圍繞一個超級工廠創建其他工廠,該超級工廠又稱為其他工廠的工廠

四、小結

工廠模式的核心本質

實例化對象不使用new,用工廠方法代替

將選擇實現類,創建對象時統一管理和控制,從而將調用者跟我們的實現類解耦

簡單工廠模式:用來生產同一等級結構中的任意產品(對於增加新的產品,需要覆蓋已有代碼)

工廠方法模式:用來生產同一等級結構中的固定產品(支持增加任意產品)

抽象工廠模式:圍繞一個超級工廠創建其他工廠,該超級工廠又稱為其他工廠的工廠

本篇文章就到這裡瞭,希望能夠給你帶來幫助,也希望您能夠多多關註WalkonNet的更多內容!

推薦閱讀: