Java工廠模式之簡單工廠,工廠方法,抽象工廠模式詳解

1、簡單工廠模式

1.定義

簡單工廠模式(Simple Factory Pattern)是指由一個工廠對象決定創建出哪一種產品類的實例。
屬於創建型模式,但它不屬於GOF23種設計模式。

2.代碼案例

假設以罐頭產品的制造為案例

第一步:定義罐頭的頂層接口類ICanned

/**
 * @Package: com.hzg.study.design.pattern.factory.simplefactory
 * @Description: 罐頭頂層接口
 * @Author: HuangZhiGao
 * @CreateDate: 2022-02-17 17:52
 */
public interface ICanned {

    /**
     * 展示罐頭名稱
     * <p/>
     *
     * @return void
     * @author HuangZhiGao
     * @date 2022/2/17/017 17:54
     */
    void showCannedName();

}

第二步:分別編寫兩個具體的實現類FruitCannedBeefCanned

/**
 * @Package: com.hzg.study.design.pattern.factory.simplefactory
 * @Description: 水果罐頭
 * @Author: HuangZhiGao
 * @CreateDate: 2022-02-17 17:56
 */
public class FruitCanned implements ICanned {

    @Override
    public void showCannedName() {
        System.out.println("名稱:水果罐頭");
    }

}
/**
 * @Package: com.hzg.study.design.pattern.factory.simplefactory
 * @Description: 牛肉罐頭
 * @Author: HuangZhiGao
 * @CreateDate: 2022-02-17 17:57
 */
public class BeefCanned implements ICanned {

    @Override
    public void showCannedName() {
        System.out.println("名稱:牛肉罐頭");
    }

}

第三步:編寫工廠類

import com.hzg.study.design.pattern.factory.common.ICanned;

/**
 * @Package: com.hzg.study.design.pattern.factory.simplefactory
 * @Description: 罐頭工廠類
 * @Author: HuangZhiGao
 * @CreateDate: 2022-02-17 18:16
 */
public class CannedFactory {

    /**
     * 創建罐頭的方法
     * <p/>
     *
     * @param clazz
     * @return com.hzg.study.design.pattern.factory.common.ICanned
     * @author HuangZhiGao
     * @date 2022/2/17/017 18:18
     */
    public ICanned createCanned(Class<? extends ICanned> clazz) {
        if (null != clazz) {
            try {
                return clazz.newInstance();
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        return null;
    }

}

第四步:main方法測試、查看類圖

import com.hzg.study.design.pattern.factory.common.BeefCanned;
import com.hzg.study.design.pattern.factory.common.FruitCanned;
import com.hzg.study.design.pattern.factory.common.ICanned;

/**
 * @Package: com.hzg.study.design.pattern.factory.simplefactory
 * @Description: 測試類
 * @Author: HuangZhiGao
 * @CreateDate: 2022-02-17 18:22
 */
public class SimpleFactoryTest {
    public static void main(String[] args) {
        CannedFactory cannedFactory = new CannedFactory();
        ICanned fruitCanned = cannedFactory.createCanned(FruitCanned.class);
        fruitCanned.showCannedName();
        System.out.println("----------------------------------------");
        ICanned beefCanned = cannedFactory.createCanned(BeefCanned.class);
        beefCanned.showCannedName();
    }
}

運行結果:

名稱:水果罐頭
—————————————-
名稱:牛肉罐頭

簡單工廠模式類圖:

簡單工廠模式類圖

3.適用場景

工廠類負責創建的對象較少,不需要關心創建對象的邏輯

4.優缺點

優點:

簡化瞭客戶端創建對象的過程

缺點:

1.工廠類職責相對較重,在一定程度上可能違背開閉原則(增加新的產品可能需要修改工廠類邏輯)
2.不易於擴展過於復雜的產品結構

2、工廠方法模式

1.定義

工廠方法模式(Factory Method Pattern)是指定義一個創建對象的接口,但讓實現這個接口的類來決定實例化哪個類,工廠方法讓類的實例化推遲到子類中進行。
屬於創建型設計模式。

2.代碼案例

需要使用到簡單工廠模式的ICannedFruitCannedBeefCanned

第一步:定義罐頭工廠頂層接口類ICannedFactory

import com.hzg.study.design.pattern.factory.common.ICanned;

/**
 * @Package: com.hzg.study.design.pattern.factory.factorymethod
 * @Description: 罐頭工廠頂層接口
 * @Author: HuangZhiGao
 * @CreateDate: 2022-02-18 10:03
 */
public interface ICannedFactory {

    /**
     * 創建罐頭方法
     * <p/>
     *
     * @return void
     * @author HuangZhiGao
     * @date 2022/2/18/018 10:04
     */
    ICanned doCreateCanned();

}

第二步:分別編寫兩個具體的工廠實現類FruitCannedFactoryBeefCannedFactory

import com.hzg.study.design.pattern.factory.common.FruitCanned;
import com.hzg.study.design.pattern.factory.common.ICanned;

/**
 * @Package: com.hzg.study.design.pattern.factory.factorymethod
 * @Description: 水果罐頭工廠類
 * @Author: HuangZhiGao
 * @CreateDate: 2022-02-18 10:05
 */
public class FruitCannedFactory implements ICannedFactory {

    @Override
    public ICanned doCreateCanned() {
        return new FruitCanned();
    }

}
import com.hzg.study.design.pattern.factory.common.BeefCanned;
import com.hzg.study.design.pattern.factory.common.ICanned;

/**
 * @Package: com.hzg.study.design.pattern.factory.factorymethod
 * @Description: 牛肉罐頭工廠類
 * @Author: HuangZhiGao
 * @CreateDate: 2022-02-18 10:08
 */
public class BeefCannedFactory implements ICannedFactory {

    @Override
    public ICanned doCreateCanned() {
        return new BeefCanned();
    }

}

第三步:main方法測試、查看類圖

import com.hzg.study.design.pattern.factory.common.BeefCanned;
import com.hzg.study.design.pattern.factory.common.FruitCanned;
import com.hzg.study.design.pattern.factory.common.ICanned;

/**
 * @Package: com.hzg.study.design.pattern.factory.simplefactory
 * @Description: 測試類
 * @Author: HuangZhiGao
 * @CreateDate: 2022-02-17 18:22
 */
public class SimpleFactoryTest {
    public static void main(String[] args) {
        CannedFactory cannedFactory = new CannedFactory();
        ICanned fruitCanned = cannedFactory.createCanned(FruitCanned.class);
        fruitCanned.showCannedName();
        System.out.println("----------------------------------------");
        ICanned beefCanned = cannedFactory.createCanned(BeefCanned.class);
        beefCanned.showCannedName();
    }
}

運行結果:

名稱:水果罐頭
—————————————-
名稱:牛肉罐頭

工廠方法模式類圖:

工廠方法模式類圖

3.適用場景

創建對象需要大量重復的代碼。
客戶端(應用層)不依賴於產品類實例如何被創建、實現等細節。
一個類通過其子類來指定創建哪個對象。

4.優缺點

優點:

1.用戶隻需關心所需產品對應的工廠,無須關心創建細節。
2.加入新產品符合開閉原則,提高瞭系統的可擴展性。

缺點:

1.類的個數容易過多,增加瞭代碼結構的復雜度。
2.增加瞭系統的抽象性和理解難度。

3、抽象工廠模式

1.定義

抽象工廠模式(Abstract Factory Pattern)是指提供一個創建一系列相關或相互依賴對象的接口,無須指定他們具體的類。
屬於創建型設計模式。

抽象工廠模式有產品族和產品等級的概念,可以通俗的理解為

產品族相當於不同品牌的產品合集,產品等級相當於不同品牌的同一種產品

例如:水果罐頭的材料信息、標簽信息組成瞭一個產品族,牛肉罐頭的材料信息、標簽信息組成瞭一個產品族

水果罐頭的材料信息、牛肉罐頭的材料信息組成一個產品等級,水果罐頭的標簽信息、牛肉罐頭的標簽信息組成一個產品等級

2.代碼案例

假設制造一個罐頭包含兩個部分(材料信息+標簽信息)

第一步:分別定義罐頭材料信息接口IMaterialInfo和罐頭標簽信息接口ITagInfo

/**
 * @Package: com.hzg.study.design.pattern.factory.abstractfactory
 * @Description: 罐頭材料信息接口
 * @Author: HuangZhiGao
 * @CreateDate: 2022-02-18 10:51
 */
public interface IMaterialInfo {

    /**
     * 打印材料信息
     * <p/>
     *
     * @return void
     * @author HuangZhiGao
     * @date 2022/2/18/018 10:57
     */
    void printMaterialInfo();

}
/**
 * @Package: com.hzg.study.design.pattern.factory.abstractfactory
 * @Description: 罐頭標簽信息接口
 * @Author: HuangZhiGao
 * @CreateDate: 2022-02-18 10:48
 */
public interface ITagInfo {

    /**
     * 打印標簽信息
     * <p/>
     *
     * @return void
     * @author HuangZhiGao
     * @date 2022/2/18/018 10:57
     */
    void printTagInfo();

}

第二步:定義罐頭的頂層工廠接口類ICannedFactory

/**
 * @Package: com.hzg.study.design.pattern.factory.abstractfactory
 * @Description: 頂層工廠接口:一個罐頭包含兩個部分(材料信息+標簽信息)
 * @Author: HuangZhiGao
 * @CreateDate: 2022-02-18 10:47
 */
public interface ICannedFactory {

    IMaterialInfo createMaterialInfo();

    ITagInfo createTagInfo();

}

第三步:分別編寫具體實現類FruitMaterialInfoFruitTagInfoBeefMaterialInfoBeefTagInfo

/**
 * @Package: com.hzg.study.design.pattern.factory.abstractfactory
 * @Description:
 * @Author: HuangZhiGao
 * @CreateDate: 2022-02-18 11:05
 */
public class FruitMaterialInfo implements IMaterialInfo {

    @Override
    public void printMaterialInfo() {
        System.out.println("材料:水果");
    }

}
/**
 * @Package: com.hzg.study.design.pattern.factory.abstractfactory
 * @Description:
 * @Author: HuangZhiGao
 * @CreateDate: 2022-02-18 11:05
 */
public class FruitTagInfo implements ITagInfo {

    @Override
    public void printTagInfo() {
        System.out.println("標簽:2022升級版水果罐頭");
    }

}
/**
 * @Package: com.hzg.study.design.pattern.factory.abstractfactory
 * @Description:
 * @Author: HuangZhiGao
 * @CreateDate: 2022-02-18 11:05
 */
public class BeefMaterialInfo implements IMaterialInfo {

    @Override
    public void printMaterialInfo() {
        System.out.println("材料:牛肉");
    }

}
/** * @Package: com.hzg.study.design.pattern.factory.abstractfactory * @Description: * @Author: HuangZhiGao * @CreateDate: 2022-02-18 11:06 */public class BeefTagInfo implements ITagInfo {    @Override    public void printTagInfo() {        System.out.println("標簽:2022升級版牛肉罐頭");    }}/**
 * @Package: com.hzg.study.design.pattern.factory.abstractfactory
 * @Description:
 * @Author: HuangZhiGao
 * @CreateDate: 2022-02-18 11:06
 */
public class BeefTagInfo implements ITagInfo {

    @Override
    public void printTagInfo() {
        System.out.println("標簽:2022升級版牛肉罐頭");
    }

}

第四步:分別編寫工廠具體實現類FruitCannedFactoryBeefCannedFactory

/**
 * @Package: com.hzg.study.design.pattern.factory.abstractfactory
 * @Description:
 * @Author: HuangZhiGao
 * @CreateDate: 2022-02-18 11:04
 */
public class FruitCannedFactory implements ICannedFactory {

    @Override
    public IMaterialInfo createMaterialInfo() {
        return new FruitMaterialInfo();
    }

    @Override
    public ITagInfo createTagInfo() {
        return new FruitTagInfo();
    }

}
/**
 * @Package: com.hzg.study.design.pattern.factory.abstractfactory
 * @Description:
 * @Author: HuangZhiGao
 * @CreateDate: 2022-02-18 11:04
 */
public class BeefCannedFactory implements ICannedFactory {

    @Override
    public IMaterialInfo createMaterialInfo() {
        return new BeefMaterialInfo();
    }

    @Override
    public ITagInfo createTagInfo() {
        return new BeefTagInfo();
    }

}

第五步:main方法測試、查看類圖

/**
 * @Package: com.hzg.study.design.pattern.factory.abstractfactory
 * @Description:
 * @Author: HuangZhiGao
 * @CreateDate: 2022-02-18 11:12
 */
public class AbstractFactoryTest {

    public static void main(String[] args) {
        ICannedFactory beefCannedFactory = new BeefCannedFactory();
        beefCannedFactory.createMaterialInfo().printMaterialInfo();
        beefCannedFactory.createTagInfo().printTagInfo();
        System.out.println("----------------------------------------");
        ICannedFactory fruitCannedFactory = new FruitCannedFactory();
        fruitCannedFactory.createMaterialInfo().printMaterialInfo();
        fruitCannedFactory.createTagInfo().printTagInfo();
    }

}

運行結果:

材料:牛肉
標簽:2022升級版牛肉罐頭
—————————————-
材料:水果
標簽:2022升級版水果罐頭

抽象工廠模式類圖:

抽象工廠模式類圖

3.適用場景

客戶端(應用層)不依賴於產品類實例如何被創建、實現等細節。
強調一系列相關的產品對象(屬於同一產品族)一起使用創建對象需要大量重復的代碼。
提供一個產品類的庫,所有的產品以同樣的接口出現,從而使客戶端不依賴於具體實現。

4.優缺點

優點:

1.具體產品在應用層代碼隔離,無須關心創建細節。
2.將一個系列的產品族統一到一起創建。

缺點:

1.規定瞭所有可能被創建的產品集合,產品族中擴展新的產品困難,需要修改抽象工廠的接口。
2.增加瞭系統的抽象性和理解難度。

4、總結

簡單工廠、工廠方法和抽象工廠的區別:

工廠方法和抽象工廠是GOF23種設計模式中的兩種,簡單工廠不是一種設計模式,可以理解為是一種約定俗成的編碼習慣。

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

推薦閱讀: