簡體   English   中英

為什么要使用工廠方法模式而不是簡單工廠

[英]Why to use Factory method pattern instead of Simple factory

我試圖了解與簡單工廠相比何時使用工廠方法模式,我知道每種方法是如何實現的,但我並不清楚。

假設我有提供字符串(汽車名稱)的客戶端,並且基於該字符串,工廠提供了對象。

我知道方法工廠滿足開/關原則,如果我擁有梅賽德斯這樣的新汽車品牌,我將不得不編輯開關盒並添加新品牌,這將是一種不好的做法。 但是然后使用Factory方法,因為沒有開關箱,我的工廠無法決定要制造哪個對象。 我想我在這里遺漏了一點。 如果我在創建汽車對象時有不同的邏輯/策略,也許應該使用工廠方法,也許是一種制造隨機汽車對象的方法/一種采用字符串並根據該字符串制造對象的方法。

如果我在Factory Method getCar()函數中使用並在返回准備使用的對象之前在其中執行更多邏輯,例如car.tuneEngine()等,這將是一個好習慣嗎?

簡單工廠

public class FordCar extends Car {

    public FordCar() {
        super("Ford", "Mondeo", 1.6);
        // TODO Auto-generated constructor stub
    }

    @Override
    public void move() {
        System.out.println("Ford moves");

    }

}

public class CarFactory {

    public Car getCar(String brand) {
        switch (brand) {
        case "ferrari":
            return new FerrariCar();
        case "ford":
            return new FordCar();
        default:
            return null;

        }
    }
}

public class Client {

    public static void main(String[] args) {

        //Simple factory
        CarFactory carFactory = new CarFactory();
        Car clientSimpleCar = carFactory.getCar("ford");
        clientSimpleCar.move();     
    }
}

工廠方法模式

public abstract class CarMethodFactory {

    public Car getCar(){
        Car car = createCar();
        return car;
    }

    public abstract Car createCar();

}

public class FordMethodFactory extends CarMethodFactory{

    @Override
    public Car createCar() {
        return new FordCar();
    }

}

public class Client {

    public static void main(String[] args) {

        CarMethodFactory carMethodFactory = new FordMethodFactory();
        Car clientMethodCar = carMethodFactory.getCar();
        clientMethodCar.move();

    }

}

出於學習目的,最好遵循工廠方法和抽象工廠的GoF定義。 GoF是圍繞基本模式的公共參考和討論。 最好警惕在幾個充滿廣告的網站上找到的許多“示例”,因為某些示例充其量會誤導您。

堅持使用GoF有2種工廠模式Factory Method和Abstract Factory。

簡單工廠不是單獨的模式,它是工廠方法的特例。 在Gof中,沒有提到將簡單工廠模式作為命名模式。 見下文。

工廠方法 :不涉及工廠對象。 顧名思義,它涉及Factory Methods()。

示例 :考慮一個TextEditor基類,其中包含C#,PHP,JS,HTML等的子類。每個子類都需要自己的SyntaxChecker對象。 TextEditor基類具有抽象的CreateSyntaxChecker()方法,並且TextEditor的每個子類都實現CreateSyntaxChecker()接口,並返回子類所需的特定SyntaxChecker。 考慮以下偽代碼的典型用法。

Editor = new PHPTextEditor;  // instantiates PHP subclass of  TextEditor
_syntaxChecker = this->CreateSyntaxChecker();     // The constructor of  
PHPTextEditor invokes its over-ridden CreateSyntaxChecker() method, which returns 
the correct PHP SyntaxChecker object.

這符合工廠方法的GoF意圖。 “定義用於創建對象的接口,但讓子類決定實例化哪個類”。

“簡單工廠” :是工廠方法的一種變體。 在此變體中,使用文本編輯器示例,TextEditor基類具有一個具體的(而不是抽象的)方法CreateSyntaxChecker(),該方法可以在子類中覆蓋,也可以不覆蓋,如果不覆蓋,則基類實現為用過的。

抽象工廠抽象工廠的GoF目的是“提供一個用於創建相關或依賴對象族的接口,而無需指定其具體類”。 實際上,這意味着要創建一個抽象的Factory類,其子類定義如何創建相關對象的族。

示例 :擴展TextEditor示例,我們意識到除了SyntaxChecker之外,還需要特定於語言的Formatter和Debug模塊。 (我們可以通過Factory Method的多個應用來實現這一點,但這涉及到編輯多個類)。 使用3個抽象方法CreateSyntaxChecker(),CreateDebugger(),CreateFormatter()定義一個抽象Factory類。 然后定義子類PHPFactory,JSFactory,HTMLFactory等,它們各自提供3種方法的實現,並返回正確的對象實例。

考慮以下偽代碼的典型用法。

Factory = new PHPFactory();
Editor = new PHPEditor(Factory);    // Constructor of PHPEditor will invoke the 3 
Factory methods to instantiate the correct versions of the SyntaxChecker, Debugger 
and Formatter objects.

我強烈建議您重構代碼以符合GoF“標准”,尤其是在學習時。 當您確定自己在做什么時,稍后便可以適應和調整以適應您的需求:-)。

當首選繼承時,首選工廠方法,因為該模式是通過繼承實現的。

僅當可接受緊密耦合時,首選“簡單工廠”,因為這種模式會將客戶端耦合到工廠實現類。

當需要松散耦合時,通常總是使用Abstract Factory。

如果願意,可以將開關替換為枚舉,並且對所允許枚舉列表的簡單迭代將返回所需的對象。 我從代碼中看到的是,第一個使用委托,第二個將您的客戶與具體工廠結合在一起。 我希望這里有第一個。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM