我正在阅读有关工厂方法模式和简单工厂的信息。事实证明,简单的工厂就足够了,我看不到工厂方法模式的用例。请阅读此链接https://www.binpress.com/factory-design-pattern/,我会提问。
1)在简单工厂中,它说这很不好,因为它违反了打开/关闭原则。我知道,但是在工厂方法模式下,它仍然违反了打开/关闭的原则。
if ('car'==$toyName) {
$toy = new NyCar();
} else if ('helicopter'==$toyName) {
$toy = new NyHelicopter();
}
如果纽约要有一个新的面包店,我们需要在这里添加。
2)在阅读链接之后,在实际上达到更好的解决方案之前,它使用了以下代码。 :
class NySimpleFactory {
public function createToy($toyName) {
$toy = null;
if ('car'==$toyName) {
$toy = new NyCar();
} else if ('helicopter'==$toyName) {
$toy = new NyHelicopter();
}
return $toy;
}
}
class NyToysFactory {
public $simpleFactory;
public function __construct(SimpleFactory $simpleFactory) {
$this->simpleFactory = $simpleFactory;
}
public function produceToy($toyName) {
$toy = null;
$toy = $this->simpleFactory->createToy($toyName);
$toy->prepare();
$toy->package();
$toy->label();
return $toy;
}
}
然后说,
开发人员快速完成新代码并将其移交给美国 工厂。两周后,手机开始响铃 开发人员办公室,因为纽约工厂正在生产 问题。原来NyToysFactory类已被修改 远程分支的开发人员,因为员工不想做 包装和标签工作。他们通过删除来修改了ProduceToy() 其label()和package()函数。
在这种情况下,简单工厂似乎无法正常工作。我们不 希望美国的分支机构能够修改ProduceToy()函数。 ProduceToy()应包含一组标准过程,并且 分支机构仅应负责创建特定于位置的信息 玩具。如果他们可以创建一个抽象类怎么办?和抽象 他们创建的类将具有具体的ProduceToy()方法 实施所有分支机构的一套标准操作程序 必须遵循。在ProduceToy()内部,它调用自己的抽象方法 createToy()获取玩具类。这样createToy()能够 封装对象创建,并且由于它是抽象的,因此将对象 创建到其子类。
问题是:a)将其移交给美国工厂意味着什么? b)或我们不希望美国的分支机构能够修改ProduceToy()函数。他们仍然可以修改ProduceToy函数,如果他们不能或者可以改变它,那有什么不同?我只是不明白为什么简单工厂对下面的示例根本不好。
无需在该链接上了解抽象工厂
答案 0 :(得分:2)
T 他的代码/问题 不会阐明“抽象工厂”或“工厂方法”。通过打开参数来确定要实例化哪个类的确是一种反模式,它鼓励违反开放式/封闭式原则。
抽象工厂
抽象工厂是关于强制相关类的家族的全部内容:
abstract class ToyFactory
+ createBear(): ToyBear
+ createElephant(): ToyElephant
class USToyFactory extends ToyFactory
+ createBear(): ToyBear -> creates USToyBear
+ createElephant(): ToyElephant -> USToyElephant
abstract class ToyBear
+ playSound()
class USToyBear extends ToyBear
+ playSound()//play US National Anthem
通过一个预期有ToyFactory的USToyFactory会强制创建美国玩具(USToyBear和USToyElephant)–这就是Abstract Factory的力量。
注意,产品(熊,大象等)是已知的AoT(提前出现)。
工厂方法
Factory方法只与将实例化延迟到子类有关。
abstract class Dashboard
+ createWidget(): Widget
abstract class Widget
+ config()
class StatsDashboard extends Dashboard
+ createWidget: Widget -> return new StatsWidget()
class StatsWidget extends Widget
调用createWidget()返回一个Widget,但是必须将要返回的具体Widget推迟到子类中(StatsDashboard返回StatsWidget)。
请注意,创建方法在继承树上声明,但在继承树下实现。
❧敏锐的读者会看到Abstract Factory方法类似于Factory Methods,这是巧合吗? –不。这是工厂方法名称的来源(它们执行具体的类实例化)。
关于“美国工厂”的困惑是正确的;这是糟糕的单词选择。作者暗示此代码可能会传递给工厂工人,这与工厂模式完全无关且令人困惑。
要解决上面的切换,您需要认识到显而易见的情况:每个条件处理程序都以某种方式关联。在这种情况下,它们都是玩具。
public function createToy($toyName) {
$toy = null;
if ('car'==$toyName) {
$toy = new NyCar();//I'm a Toy
} else if ('helicopter'==$toyName) {
$toy = new NyHelicopter();//I'm a Toy
}
return $toy;
}
使用多态性,我们可以通过创建一组同级类来满足开闭原则:
abstract class Toy
+ operate()
Car extends Toy
Helicopter extends Toy
some_toy.operate();
添加到切换案例只不过是创建另一个同级类。
Dependency injection应该用于实例化具体的Toy。
我希望这会有所帮助!