[英]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.