If the user is known only at the time, the order is created, you could implement a getCurrentUser() function that is called by the factory. If that is possible, the factory function obviously wins. If not, then there is no gain.
If, in the past, you didn't know there would ba a customer needed, you probably also could not know whether it's possible to implement a getCurrentUser() function. The chances of the factory method paying off may not be very good but they don't always equal 0.
The real benefit to using a Factory is that it is a façade which hides just how you go about creating an object that fulfills the Order role. To be more exact, the Factory knows that you're really making a FooBarOrder, and nothing else has to be changed to switch from always making a FooBarOrder to sometimes making a BarFooOrder instead. (If Java let you intercept new and make a subclass instead, there would be no need for Factories. But it doesn't – fairly reasonably, to be fair – so you have to have them. Object systems which allow subclassing the class of classes are more flexible in this regard.)
No, because the dependency for the factory should be injected via the factories constructor, and you are only constructing the factory in one place, but the passing it as the dependency to everything that needs to create an order. The things which are getting orders from the factory are still calling the same method, CreateOrder() or whatever, and so that code is unchanged.
The dependencies should all be wired up in a single place, the composition root, and that should be the only place that needs to change, to add the new dependency to the factory
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();
}
在书中给出的示例中,为 Order 建立一个工厂会有所帮助,因为它会减少直接使用构造函数的地方的数量;只需要修改创建工厂的一个位置即可将 Customer 存储为工厂的附加字段;工厂的其他用途都不需要修改。相比之下,在不使用工厂的情况下,直接使用构造函数的情况比比皆是,并且它们中的每一个都必须更新才能以某种方式获取对 Customer 对象的访问。
The factory pattern can ease the pain of adding a dependency, because a factory may contain state and, in fact, can encapsulate multiple dependencies (e.g. instead of providing three dependencies, all needed to invoke some object's constructor, you now provide only a single factory object, where the factory contains those three objects that are needed to be provided to the constructor).
To give an example, compare:
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();
}
And:
void DoIt(const DependencyCFactory& factory) {
int x = ComputeX();
std::unique_ptr<DependencyC> dependency_c(factory->Create(x));
dependency_c->DoStuff();
}
Note that the second version required fewer dependencies to the method "DoIt". This does not mean that those dependencies aren't need in the entire program (indeed, the program still makes use of DependencyA and DependencyB in the implementaiton of the factory). However, by structuring it this way, that dependency can be isolated to just the factory code, which keeps other code simpler, makes it easier to change the dependencies of DependencyC (now only the factory, itself, needs to be updated, not every place that instantiates DependencyC), and can even have certain safety/security benefits (e.g. if DependencyA and DependencyB are sensitive such as database passwords or API keys, limiing their usage to the factory reduces the chances of mishandling, compared to cases where you pass these around everywhere that you need to use the databse or API, for example).
In the example given in the book, the reason why having a factory for the Order would have helped is that it would have reduced the number of places where the constructor is used directly; only the one place that created the factory would need to be modified to store the Customer as an additional field of the factory; none of the other uses of the factory would need to be modified. By comparison, without the use of the factory, direct uses of the constructor abound, and each one of them must be updated to somehow obtain access to the Customer object.
发布评论
评论(5)
如果仅在创建订单时知道用户,您可以实现由工厂调用的
getCurrentUser()
函数。如果这是可能的,那么工厂函数显然会获胜。如果没有,那就没有收获。
如果在过去,您不知道会有客户需要,您可能也不知道是否可以实现
getCurrentUser()
函数。 工厂方法获得回报的机会可能不是很好,但并不总是等于 0。If the user is known only at the time, the order is created, you could implement a
getCurrentUser()
function that is called by the factory.If that is possible, the factory function obviously wins. If not, then there is no gain.
If, in the past, you didn't know there would ba a customer needed, you probably also could not know whether it's possible to implement a
getCurrentUser()
function. The chances of the factory method paying off may not be very good but they don't always equal 0.使用工厂的真正好处在于,它是一个外观,隐藏了您如何创建履行订单角色的对象。更准确地说,Factory 知道您确实在创建 FooBarOrder,并且无需更改任何其他内容即可从始终创建 FooBarOrder 切换到有时创建 BarFooOrder。 (如果 Java 让你拦截
new
并创建一个子类,那么就不需要工厂了。但公平地说,它没有——相当合理地——所以你必须拥有它们。对象系统允许对类进行子类化,在这方面更加灵活。)The real benefit to using a Factory is that it is a façade which hides just how you go about creating an object that fulfills the Order role. To be more exact, the Factory knows that you're really making a FooBarOrder, and nothing else has to be changed to switch from always making a FooBarOrder to sometimes making a BarFooOrder instead. (If Java let you intercept
new
and make a subclass instead, there would be no need for Factories. But it doesn't – fairly reasonably, to be fair – so you have to have them. Object systems which allow subclassing the class of classes are more flexible in this regard.)不,因为工厂的依赖项应该通过工厂构造函数注入,并且您只在一处构建工厂,但将其作为依赖项传递给需要创建订单的所有内容。从工厂获取订单的事物仍然调用相同的方法,CreateOrder() 或其他方法,因此代码保持不变。
依赖项应全部连接在一个位置,即 组合根,这应该是唯一需要更改的地方,以将新的依赖项添加到工厂
No, because the dependency for the factory should be injected via the factories constructor, and you are only constructing the factory in one place, but the passing it as the dependency to everything that needs to create an order. The things which are getting orders from the factory are still calling the same method, CreateOrder() or whatever, and so that code is unchanged.
The dependencies should all be wired up in a single place, the composition root, and that should be the only place that needs to change, to add the new dependency to the factory
您告诉工厂新的依赖项,并让它为您添加它。对工厂的方法调用应该保持不变。
You tell the factory about the new dependency, and let it add it for you. The method call to the factory should be unchanged.
工厂模式可以减轻添加依赖项的痛苦,因为工厂可能包含状态,事实上,可以封装多个依赖项(例如,您现在只提供一个工厂对象,其中工厂包含这三个对象,而不是提供调用某个对象的构造函数所需的三个依赖项)需要提供给构造函数)。
举个例子,比较:
和:
请注意,第二个版本需要对方法“DoIt”的依赖较少。这并不意味着整个程序不需要这些依赖项(事实上,程序在工厂的实现中仍然使用 DependencyA 和 DependencyB)。然而,通过这种方式构建它,该依赖关系可以被隔离到工厂代码,这使得其他代码更简单,更容易更改
DependencyC
的依赖关系(现在只有工厂本身需要要更新,不是每个实例化DependencyC
的地方),甚至可以具有一定的安全/保障优势(例如,如果DependencyA
和DependencyB
是敏感的例如,与将这些密码传递到需要使用数据库或 API 的任何地方的情况相比,将它们的使用限制在工厂可以减少误处理的可能性)。在书中给出的示例中,为
Order
建立一个工厂会有所帮助,因为它会减少直接使用构造函数的地方的数量;只需要修改创建工厂的一个位置即可将Customer
存储为工厂的附加字段;工厂的其他用途都不需要修改。相比之下,在不使用工厂的情况下,直接使用构造函数的情况比比皆是,并且它们中的每一个都必须更新才能以某种方式获取对Customer
对象的访问。The factory pattern can ease the pain of adding a dependency, because a factory may contain state and, in fact, can encapsulate multiple dependencies (e.g. instead of providing three dependencies, all needed to invoke some object's constructor, you now provide only a single factory object, where the factory contains those three objects that are needed to be provided to the constructor).
To give an example, compare:
And:
Note that the second version required fewer dependencies to the method "DoIt". This does not mean that those dependencies aren't need in the entire program (indeed, the program still makes use of DependencyA and DependencyB in the implementaiton of the factory). However, by structuring it this way, that dependency can be isolated to just the factory code, which keeps other code simpler, makes it easier to change the dependencies of
DependencyC
(now only the factory, itself, needs to be updated, not every place that instantiatesDependencyC
), and can even have certain safety/security benefits (e.g. ifDependencyA
andDependencyB
are sensitive such as database passwords or API keys, limiing their usage to the factory reduces the chances of mishandling, compared to cases where you pass these around everywhere that you need to use the databse or API, for example).In the example given in the book, the reason why having a factory for the
Order
would have helped is that it would have reduced the number of places where the constructor is used directly; only the one place that created the factory would need to be modified to store theCustomer
as an additional field of the factory; none of the other uses of the factory would need to be modified. By comparison, without the use of the factory, direct uses of the constructor abound, and each one of them must be updated to somehow obtain access to theCustomer
object.