工廠方法模式

簡單工廠模式(Simple Factory Pattern)又叫靜態(tài)工廠方法模式(Static FactoryMethod Pattern)。專門定義一個類來負(fù)責(zé)創(chuàng)建其它類的實例,由它來決定實例化哪個具體類,從而避免了在客戶端代碼中顯式指定,實現(xiàn)了解耦。該類由于可以創(chuàng)建同一抽象類(或接口)下的不同子類對象,就像一個工廠一樣,因此被稱為工廠類。

如圖,我們設(shè)計一個簡單的運算器來解釋該模式。


簡單工廠模式

簡單工廠類:

public class OptionerFactory {
    public static Optioner createOptioner(String opt) {
        Optioner optioner = null;
        switch (opt) {
            case "+":
                optioner = new AddOptioner();
                break;
            case "-":
                optioner = new SubOptioner();
                break;
            case "*":
                optioner = new MulOptioner();
                break;
            case "/":
                optioner = new DivOptioner();
                break;
        }
        return optioner;
    }
}
  • Factory:簡單工廠模式的核心,負(fù)責(zé)實現(xiàn)創(chuàng)建所有實例的內(nèi)部邏輯。Fcatory 類可以被外界直接調(diào)用,創(chuàng)建所需的產(chǎn)品對象。

運算類:

public class Optioner {
    private int oNumFirst;//第一個數(shù)
    private int oNumSecond;//第二個數(shù)
    public int getoNumFirst() {
        return oNumFirst;
    }
    public void setoNumFirst(int oNumFirst) {
        this.oNumFirst = oNumFirst;
    }
    public int getoNumSecond() {
        return oNumSecond;
    }
    public void setoNumSecond(int oNumSecond) {
        this.oNumSecond = oNumSecond;
    }
    public Optioner() {
    }
    public Optioner(int oNumFirst, int oNumSecond) {
        this.oNumFirst = oNumFirst;
        this.oNumSecond = oNumSecond;
    }
    public int getReuslt() {
        return 0;
    }
}
  • Product:簡單工廠模式所創(chuàng)建的所有對象的父類,它負(fù)責(zé)描述所有實例所共有的公共接口。

具體運算類:

/**
 * 加法運算
 */
public class AddOptioner extends Optioner {
    @Override
    public int getReuslt() {
        return getoNumFirst() + getoNumSecond();
    }
}
/**
 * 減法運算
 */
public class SubOptioner extends Optioner {
    @Override
    public int getReuslt() {
        return getoNumFirst() - getoNumSecond();
    }
}
/**
 * 乘法運算
 */
public class MulOptioner extends Optioner {
    @Override
    public int getReuslt() {
        return getoNumFirst() * getoNumSecond();
    }
}
/**
 * 除法運算
 */
public class DivOptioner extends Optioner {
    @Override
    public int getReuslt() {
        if (getoNumSecond() == 0) {
            System.out.println("除數(shù)不能為0");
            return -1;
        } else {
            return getoNumFirst() / getoNumSecond();
        }
    }
}
  • Concrete Product:簡單工廠模式的創(chuàng)建目標(biāo),所有創(chuàng)建的對象都是充當(dāng)這個角色的某個具體類的實例。

開—閉原則:是說軟件實體(類、模塊、函數(shù)等等)應(yīng)該可以擴(kuò)展,但是不可修改。

功能的擴(kuò)展體現(xiàn)在引進(jìn)新的產(chǎn)品上,開—閉原則要求新的產(chǎn)品加入系統(tǒng)時,無需對現(xiàn)有代碼進(jìn)行修改。在簡單工廠模式中,這點對于產(chǎn)品角色是成立的,而對于工廠角色是不成立的。產(chǎn)品角色無需修改就課接納新的產(chǎn)品。

但對于工廠角色來說,增加新產(chǎn)品要修改程序;工廠角色必須知道每一種產(chǎn)品,如何創(chuàng)建它們,以及何時向客戶端提供它們。所以,簡單工廠角色只在有限的程度上支持開—閉原則。

簡單工廠模式的最大優(yōu)點在于工廠類中包含了必要的邏輯判斷,根據(jù)客戶端的選擇條件動態(tài)實例化相關(guān)的類。對客戶端來說,去除了與具體產(chǎn)品的依賴。

問題是增加功能,就要改變簡單工廠類并且不滿足開閉原則。

進(jìn)而引出工廠方法模式。工廠方法模式(Factory Method Pattern)又稱為工廠模式,也叫多態(tài)工廠模式或者虛擬構(gòu)造器模式。在工廠方法模式中,工廠父類定義創(chuàng)建產(chǎn)品對象的公共接口,具體的工廠子類負(fù)責(zé)創(chuàng)建具體的產(chǎn)品對象。每一個工廠子類負(fù)責(zé)創(chuàng)建一種具體產(chǎn)品。

如圖:

工廠方法模式

和簡單工廠模式直接使用靜態(tài)工廠方法創(chuàng)建產(chǎn)品對象不同,在工廠方法,客戶端通過實例化具體的工廠類,并調(diào)用其創(chuàng)建實例接口創(chuàng)建具體產(chǎn)品類的實例。根據(jù)依賴倒置原則,具體工廠類的實例由工廠接口引用(客戶端依賴于抽象工廠而非具體工廠),具體產(chǎn)品的實例由產(chǎn)品接口引用(客戶端和工廠依賴于抽象產(chǎn)品而非具體產(chǎn)品)。

接下來,畫一下類圖:

運算器工廠方法模式類圖

我們所需要做的:

簡單工廠 →加Operation子類
        →改工廠類(case)
工廠方法 →加Operation子類
        →加工廠子類
        →修改客戶端

這樣整個工廠和產(chǎn)品體系其實都沒有修改的變化,而只是擴(kuò)展的變化,完全符合開閉原則,從這個角度講優(yōu)于簡單工廠模式。

工廠方法模式實現(xiàn)時,客戶端需要決定實例化哪一個工廠來實現(xiàn)運算類,選擇判斷的問題還是存在,也就是說,工廠方法把簡單工廠的內(nèi)部邏輯判斷移到客戶端代碼進(jìn)行。想要增加功能,本來是改工廠類,而現(xiàn)在是修改客戶端。

工廠方法模式是簡單工廠模式的進(jìn)一步抽象和推廣。它克服了簡單工廠違背開閉原則的缺點,又保持了封裝對象創(chuàng)建過程的優(yōu)點,使得更換對象時,不需要做大的改動,降低了客戶程序與產(chǎn)品對象的耦合。

但是由于每加一個產(chǎn)品,就需要加一個產(chǎn)品工廠的類,增加了額外的工作量。而且無法避免修改客戶端的代碼。

當(dāng)然,我們可以通過反射→避免分支判斷問題。后面補(bǔ)充。

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

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

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