8

这困扰了我一段时间,我不知道这是否是一个神话。

工厂模式似乎可以减轻为类添加依赖项的痛苦。

例如,在一本书中,它有这样的东西

假设您有一个名为 Order 的类。最初它不依赖于任何东西。因此,您不必费心使用工厂来创建 Order 对象,而只需使用 plain new 来实例化对象。但是,您现在需要创建与客户关联的订单。您需要更改数百万个位置才能添加此额外参数。如果您为 Order 类定义了一个工厂,那么您就可以满足新的要求而没有同样的痛苦。

这与向构造函数添加额外参数有何不同?我的意思是你仍然需要为工厂提供一个额外的参数,这也被数百万个地方使用,对吧?

4

5 回答 5

5

如果仅在创建订单时知道用户,则可以实现getCurrentUser()工厂调用的函数。
如果这是可能的,那么工厂功能显然会胜出。如果没有,那么就没有收获。

如果在过去,您不知道会有客户需要,您可能也不知道是否可以实现某个getCurrentUser()功能。工厂方法获得回报的机会可能不是很好,但并不总是等于 0。

于 2010-04-23T10:16:00.000 回答
3

使用工厂的真正好处是它是一个外观,它隐藏了您如何创建一个满足订单角色的对象。更准确地说,Factory 知道您确实在制作 FooBarOrder,无需更改任何其他内容即可从始终制作 FooBarOrder 切换到有时制作 BarFooOrder。(如果 Java 让你拦截new并创建一个子类,那么就不需要工厂。但它不需要——相当合理,公平地说——所以你必须拥有它们。允许对类进行子类化的对象系统是在这方面更灵活。)

于 2010-04-23T10:03:19.903 回答
2

不,因为工厂的依赖项应该通过工厂构造函数注入,并且您只是在一个地方构建工厂,但是将其作为依赖项传递给需要创建订单的所有内容。从工厂获得订单的东西仍然调用相同的方法,CreateOrder() 或其他方法,因此代码不变。

依赖项都应该连接在一个地方,即组合根,并且应该是唯一需要更改的地方,以将新依赖项添加到工厂

于 2010-04-23T09:52:44.567 回答
1

你告诉工厂新的依赖,让它为你添加它。对工厂的方法调用应该保持不变。

于 2010-04-23T09:52:30.013 回答
1

工厂模式可以减轻添加依赖项的痛苦,因为工厂可能包含状态,实际上可以封装多个依赖项(例如,不是提供三个依赖项,所有这些依赖项都需要调用某个对象的构造函数,您现在只提供一个工厂对象,其中工厂包含需要提供给构造函数的这三个对象)。

举个例子,比较一下:

void DoIt(const DependencyA& a, const DependencyB& b) {
   // NOTE: "x" is a contrived additional variable that we add here to
   // justify why we didn't just pass DependencyC directly.
   int x = ComputeX(); 
   std::unique_ptr<DependencyC> dependency_c(new DependencyC(a, b, x));
   dependency_c->DoStuff();
}

和:

void DoIt(const DependencyCFactory& factory) {
  int x = ComputeX();
  std::unique_ptr<DependencyC> dependency_c(factory->Create(x));
  dependency_c->DoStuff();
}

请注意,第二个版本需要对“DoIt”方法的依赖较少。这并不意味着整个程序不需要这些依赖项(实际上,程序在工厂的实现中仍然使用了DependencyA和DependencyB)。但是,通过以这种方式构建它,可以将依赖项隔离到工厂代码,这使其他代码更简单,更容易更改DependencyC(现在只有工厂本身需要更新,而不是每个地方都需要更新)实例化DependencyC),甚至可以有一定的安全/保障好处(例如,如果DependencyADependencyB是敏感的,例如数据库密码或 API 密钥,将它们的使用限制在工厂可以减少错误处理的机会,例如,与在需要使用数据库或 API 的任何地方传递这些信息的情况相比)。

在书中给出的例子中,有一个工厂Order会有所帮助的原因是它会减少直接使用构造函数的地方的数量;只需修改创建工厂的一个地方以将其存储Customer为工厂的附加字段;工厂的其他用途都不需要修改。相比之下,在不使用工厂的情况下,直接使用构造函数的情况比比皆是,而且它们中的每一个都必须更新才能以某种方式获得对Customer对象的访问权。

于 2010-04-23T09:53:00.400 回答