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