有一个工厂用于创建对象的好处?

时间:2010-04-24 04:50:36

标签: php design-patterns

我正在努力了解工厂设计模式。

我不明白为什么在客户端和产品(客户想要的对象)之间建立一个中间人是好的。

没有工厂的例子:

$mac = new Mac();

工厂的例子:

$appleStore = new AppleStore();
$mac = $appleStore->getProduct('mac');

工厂模式如何将客户与产品分离?

有人会举例说明未来的代码更改会影响示例1的否定,但是示例2中是肯定的,所以我理解解耦的重要性吗?

感谢。

3 个答案:

答案 0 :(得分:5)

我认为这与构建某些类型的对象所需的资源有关。

非正式地说,如果你告诉某人建造一台Mac,这将是一个艰苦的过程,需要多年的设计,开发,制造和测试,而且可能做得不对。每个Mac都必须重复此过程。但是,如果你介绍一个工厂,所有的辛苦工作只需要做一次,那么Mac就可以更便宜地生产。

现在考虑Joomla的factory.php。据我所知,JFactory的主要目的是汇集对象并确保不会复制应该相同的对象。例如,JFactory::getUser()将返回对一个且仅一个对象的引用。如果该用户对象中的某些内容发生了变化,它将随处出现。另请注意,JFactory::getUser()返回引用,而不是新对象。这是你无法用构造函数做的事情。

通常,在构造对象时需要本地上下文,并且该上下文可能会持久存在并可能采用多种形式。例如,可能有一个MySQL数据库保存用户。如果使用构造函数创建User对象,则需要将Database对象传递给构造函数(或者让它依赖于全局变量)。如果您决定将应用程序切换到PostgreSQL,则Database对象的语义可能会发生变化,从而导致需要检查构造函数的所有用法。全局变量让我们隐藏这些细节,工厂也是如此。因此,用户工厂会将构造User对象的细节与需要User对象的位置分离。

工厂何时有用?构造对象时涉及背景细节。什么时候构造者更好?当全局变量足够时。

答案 1 :(得分:2)

答案 2 :(得分:1)

此示例返回Mac类型的对象,它永远不会有任何不同:

$mac = new Mac();

它不能是Mac的子类,也不能是与Mac的接口匹配的类。

以下示例可能会返回Mac类型的对象或工厂决定的其他类型的对象。

$appleStore = new AppleStore();
$mac = $appleStore->getProduct('mac');

您可能需要一组Mac的子类,每个子类代表不同的Mac模型。然后在工厂中编写代码以决定使用哪些子类。您无法使用new运算符执行此操作。

因此,工厂为您提供了更多的对象创建灵活性。灵活性通常与解耦密切相关。


重新评论:我不会说从不使用new。事实上,我确实使用new来创建大多数简单对象。但它与编写客户端代码的人无关。工厂模式适用于需要可以选择要动态实例化的类的体系结构。

在Apple Store示例中,您可能需要一些简单的代码来实例化产品并将其添加到购物车中。如果您使用new并且每种不同的产品类型都有不同的对象类型,则必须编写一个巨大的case语句,以便创建相应类型的new对象。每次添加产品类型时,都必须更新case语句。您可能在应用程序的其他部分中有几个case语句。

通过使用工厂,您将只有一个地方可以更新,它知道如何获取参数并实例化正确类型的对象。您的应用中的所有位置都会隐式获得对新类型的支持,而无需更改代码。无论您是唯一的开发人员还是团队成员,这都是一场胜利。

但是,如果您不需要支持各种子类型,则不需要工厂。在简单的情况下继续使用new