天天看點

設計模式之工廠模式_單例模式和工廠模式

大家好,又見面了,我是你們的朋友全棧君。

概述

工廠模式(Factory Pattern)屬于建立型模式,它提供了一種建立對象的最佳方式。

在工廠模式中,我們在建立對象時不會對用戶端暴露建立邏輯,并且是通過使用一個共同的接口來指向新建立的對象。

工廠模式旨在與解決接口實作類選擇這一類問題,讓執行個體建立的代碼使用執行個體的方法解耦。

當我們需要根據不同的明确條件下建立不同的執行個體的時候,就可以使用工廠模式。

工廠模式分為三類:

  • 工廠方法模式:一個工廠生産固定的一個類。
  • 簡單/靜态工廠模式:一個工廠生産固定種類的多個類。
  • 抽象工廠模式:一個抽象工廠生産一

一、工廠方法模式

假設我們有一個導出報表的抽象類:

/**
 * 檔案導出接口
 */
public abstract class Exporter {
    void export();
}           

複制

他現在有一個Excel導出實作類:

/**
 * Excel導出實作類
 */
public class ExcelExporter extend Exporter{
    
    private String modelPath;
    
    private String fileName;
    
    @Override
    public void export() {
        System.out.println("導出Excel:"+"模闆路徑:"+ modelPath +"檔案名:" + fileName);
    }
    
    public ExcelExporter(String modelPath, String fileName) {
        this.modelPath = modelPath;
        this.fileName = fileName;
    }
}           

複制

現在我們需要在一個方法裡去調用它,讓客戶可以導出報表:

//從配置中讀取模闆路徑
String modelPath = Config.getExcelModelPath();
//擷取檔案名
String fileName = name + Config.getExcelLastName(); 
ExcelExporter ee = new ExcelExporter(modelPath, fileName);
//一些其他業務邏輯
... ...
ee.export();           

複制

我們在很多方法都需要調用這個類,但是每次使用都要寫那麼多行代碼,實在太麻煩,而且萬一忽然modelPath或者fileName這些參數要改,那工程量也很讓人頭痛。

是以我們可以把擷取對象的操作提出來,把讀取配置路徑等方法都單獨提出來,最後統一放到一個工廠類裡:

/**
 * Excel檔案導出實作類的工廠
 */
public class ExcelExporterFactory {
    
    public String getExcelLastName(){
        return Config.getExcelLastName();
    }

    public String getModePath(){
        return Config.getExcelModelPath();
    }

    public ExcelExporter getExporter(String type) {
        return new ExcelExporter(getModePath(),getExcelLastName());
    }
}           

複制

最後使用的時候不需要在意執行個體化的過程,隻需要調用方法擷取新對象就行了:

ExcelExporterFactory factory = new ExcelExporterFactory();
factory.getExcelExporter().export();           

複制

值得一提的是,由于工廠的特殊性,它大多數情況下都是單例的。

不難發現,工廠方法模式有以下優點:

  • 1:用戶端不需要在負責對象的建立,明确了各個類的職責;
  • 2:如果有新的對象增加,隻需要增加一個具體的類和具體的工廠類即可;
  • 3:不會影響已有的代碼,後期維護容易,增強系統的擴充性。

二、簡單/靜态工廠

工廠方法模式确實好,但是有時候我們需要用工廠生産的往往隻有特定的幾個類,其他的直接new就可以了。這種情況下在為每一個類單獨建立一個工廠類太過麻煩,為此我們讓一個工廠去生産固定的那幾種類,這就是簡單/靜态工廠。

假設我們目前隻需要導出Excel和word類型的報表,我們在上一個例子的基礎上再加一WordExporter實作類:

/**
 * Excel導出實作類
 */
public class WordExporter extend Exporter {

    private String modelPath;

    private String fileName;

    @Override
    public void export() {
        System.out.println("導出Word!");
    }

    public WordExporter(String modelPath, String fileName) {
        this.modelPath = modelPath;
        this.fileName = fileName;
    }

}           

複制

然後我們改造一下原本的ExcelExporterFactory,讓他也能生産WordExporter:

/**
 * 檔案導出實作類的簡單工廠
 */
public class ExporterFactory {

    public String getExcelLastName(){
        return Config.getExcelLastName();
    }

    public String getModePath(){
        return Config.getExcelModelPath();
    }

    public Exporter getExporter(String type) {
        //根據條件傳回對應的執行個體
        if ("word".equals(type)) {
            return new WordExporter(getModePath(),getExcelLastName());
        } else if ("excel".equals(type)) {
            return new ExcelExporter(getModePath(),getExcelLastName());
        }else {
            throw new RuntimeException("導出類型不存在!");
        }
    }

}           

複制

當我們要調用的時候,直接通過工廠調用就可以了:

ExporterFactory factory = new ExporterFactory();
factory.getExcelExporter(type).export();           

複制

這個就是簡單工廠。

在簡單工廠的基礎上,我們不難看出,現在的ExporterFactory總是隻能生産固定的那幾種類,那麼其實調用

getExporter()

去擷取實作類的時候根本沒必要new一個新工廠。

于是我們将這個工程裡的所有方法都變成靜态方法,調用的時候就很友善了:

ExportService es = ExporterFactory.getExporter(type);           

複制

這個就是靜态工廠。

三、抽象工廠模式

簡單工廠對工廠方法做了減法,簡化了代碼結構,但是簡單工廠違背了開閉原則,如果要添加新的産品,就需要修改工廠類代碼。而傳統的工廠方法模式,如果有很多産品的情況下又會建立過多的工廠類。

為此,我們對工廠方法模式做加法,就有了抽象工廠模式:由頂層的抽象工廠提供生産産品的接口,具體的生産過程由繼承了抽象工廠的子工廠去實作。

舉個例子:

根據上文,我們現在有了Exporter接口,和兩個實作類ExcelExporter和WordExporter,現在我們有了新的需求:

導出的報表要分成兩種類型:有資料的表格和沒有資料的表格。(empty)

1.産品的抽象

我們先對産品進行抽象:

Exporter這個類不管是否有資料,都需要導出方法

export()

,然後根據表格是否有資料,還需要一個方法

empty()

我們将其分為由原本的ExcelExporter和WordExporter也變成抽象類,隻實作各種的

export()

方法,然後再針對ExcelExporter和WordExporter再拆分,得到無資料表格類EmptyExcelExporter,EmptyWordExporter,有資料表格類FullExcelExporter,FullWordExporter。

設計模式之工廠模式_單例模式和工廠模式

2.工廠的抽象

由于産品的層級變成了三層,原本用于生産WordExporter和ExcelExporter的工廠ExporterFactory也要進行拆分。

将ExporterFactory變為接口,裡面規定了

getExcelExporter()

getWordExporter()

兩個接口方法,然後由EmptyExporterFactory還有FullExporterFactory工廠去

設計模式之工廠模式_單例模式和工廠模式

不難看出,抽象工廠通過多了一層抽象,減少了工廠類的數量,但是當要添加一類産品,比如加一個導出PDF類,同樣要修改ExporterFactory及其實作類。

釋出者:全棧程式員棧長,轉載請注明出處:https://javaforall.cn/170790.html原文連結:https://javaforall.cn