抽象工厂:实现方式

时间:2018-10-31 09:27:56

标签: oop design-patterns abstract-factory

我现在正在学习设计模式,并为每种模式读取不同的资源。我对模式抽象工厂有疑问。我了解了两种实现此目的的方法。我将使用此工厂来编写,而不会意识到。例如,我制作了不同的门。

第一种方式。我们有门工厂的通用类,其中包括制造不同类型门的不同方法(返回合适的门类):

$doorFactory = new DoorFactory();
$door1 = $doorFactory->createWoodDoor();

$doorFactory = new DoorFactory();
$door2 = $doorFactory->createSteelDoor();

第二种方式。我们有父类DoorFactory,并扩展了WoodDoorFactory和SteelDoorFactory的类。此类实现相同的方法createDoor(并返回适当的Door类)

$woodDoorFactory = new WoodDoorFactory();
$door1 = $woodDoorFactory->createDoor();

$steelDoorFactory = new SteelDoorFactory();
$door2 = $steelDoorFactory->createDoor();

您如何看待,哪种方法更理想,更规范?

2 个答案:

答案 0 :(得分:0)

请想象一下您的工厂经过时的情况,并且客户代码需要询问的工厂只是创建一扇门(不关心木材和钢铁),您将了解为什么第二种方法更好。假设我们有一个方法Client的类foo,该类使用工厂(我使用Java,但应该很容易理解):

class Client {
    private DoorFactory factory;
    public Client(DoorFactory factory) { this.factory = factory; }
    public void foo() {
        Door door = factory.createDoor();
    }
}

现在,您可以将WoodDoorFactorySteelDoorFactoryWhateverDoorFactory传递给Client的构造函数。

此外,更不用说您的第一种方法可能违反了The Single Responsibility Principles,因为DoorFactory类知道许多可能无关的事情。实际上,它知道如何创建需要Wood APIs的木门(仅作为示例),它知道如何创建需要Steel APIs的钢门。这显然减少了在另一个不想依赖DoorFactoryWood APIs的环境中重用Steel APIs类的机会。您的第二种方法不会发生此问题。

答案 1 :(得分:0)

与其他答案一样,我在实践中通常也更喜欢第二种方法。我发现它是一种更灵活,更有用的依赖项注入方法。

也就是说,我确实认为在某些情况下第一种方法即使没有更好也效果很好-只是不那么普遍。我想到的一个示例是XML文档对象模型。如果您曾经使用过Microsoft的c ++ XML DOM文档API,那么您将熟悉这种方法(请参见https://docs.microsoft.com/en-us/previous-versions/windows/desktop/ms760218(v%3dvs.85)

在这种情况下,XML文档中可以包含数量有限的定义良好的元素。也不需要能够动态扩展可放入XML文档中的元素的类型-所有这些都是由某些标准委员会预先确定的。因此,第一种工厂方法在这里起作用,因为您可以预先确定需要从一开始就可以创建的所有不同类型的事物。

在这种情况下的另一个优点是,通过使XML Document类成为其中包含的所有元素的工厂,XML Document可以完全控制那些内部对象的生命周期。注意:它们不允许在多个XML Document实例中使​​用相同的子元素。如果要使用一个XML文档中的节点并将其放置在另一个XML文档中,则将需要遍历第二个XML文档以生成新的node元素以及任何和所有子元素的副本。 / p>

在这种情况下,与OP中的示例的一个显着区别是,不是工厂方法用于提供创建同一类型事物的多种方法,工厂知道如何创建一堆高度相关的对象(并且连接)对象类型。