与简单工厂相比,我试图了解何时使用工厂方法模式,我知道每种方法是如何实现的,但我不完全明白这一点。
假设我有提供字符串(汽车名称)的客户端,并基于该字符串,工厂提供了对象。
我知道方法工厂满足打开/关闭的原则,如果我拥有梅赛德斯这样的新汽车品牌,我将不得不编辑开关盒并添加新品牌,这将是一种不好的做法。但是然后使用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();
}
}
答案 0 :(得分:2)
出于学习目的,可能需要遵循工厂方法和抽象工厂的GoF定义。 GoF是围绕基本模式的公共参考和讨论。最好警惕在几个充满广告的网站上找到的许多“示例”,因为某些示例充其量会误导您。
使用GoF标记有2种工厂模式Factory Method和Abstract Factory。
简单工厂不是单独的模式,它是工厂方法的特例。在Gof中,没有提到将简单工厂模式作为命名模式。见下文。
工厂方法:这不涉及Factory对象。顾名思义,它涉及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“标准”,尤其是在学习时。当您确定自己在做什么时,以后可以根据自己的需要进行适应和调整:-)。
答案 1 :(得分:0)
当首选继承时,首选“工厂方法”,因为该模式是通过继承实现的。
仅当可接受紧密耦合时,首选“简单工厂”,因为这种模式会将客户端耦合到工厂实现类。
当需要松散耦合时,通常首选Abstract Factory。
答案 2 :(得分:0)
如果愿意,可以将开关替换为枚举,并且对所允许枚举列表的简单迭代将返回所需的对象。 我从代码中看到的是,第一个使用委托,第二个将您的客户与具体工厂结合在一起。我希望这里是第一个。