C++中的这一件事让我感到不舒服很长一段时间,因为我老实说不知道该怎么做,尽管听起来很简单:
目标:允许客户端使用工厂方法而不是对象的构造函数来实例化某个对象,而不会产生不可接受的后果和性能损失.
"工厂方法模式"是指对象内部的静态工厂方法或另一个类中定义的方法,或全局函数.通常只是"将类X的实例化的正常方式重定向到构造函数之外的任何其他位置的概念".
让我略过一些我想到过的可能答案.
这听起来不错(实际上通常是最好的解决方案),但不是一般的补救措施.首先,有些情况下,对象构造是一个复杂的任务,足以证明它被提取到另一个类.但即使将这个事实放在一边,即使对于仅使用构造函数的简单对象,通常也不会这样做.
我所知道的最简单的例子是2-D Vector类.这么简单,但很棘手.我希望能够从笛卡尔坐标和极坐标两者构造它.显然,我做不到:
struct Vec2 {
Vec2(float x, float y);
Vec2(float angle, float magnitude); // not a valid overload!
// ...
};
Run Code Online (Sandbox Code Playgroud)
我的自然思维方式是:
struct Vec2 {
static Vec2 fromLinear(float x, float y);
static Vec2 fromPolar(float angle, float magnitude);
// ...
};
Run Code Online (Sandbox Code Playgroud)
其中,而不是构造函数,导致我使用静态工厂方法...这实际上意味着我正在以某种方式实现工厂模式("类成为自己的工厂").这看起来不错(并且适合这种特殊情况),但在某些情况下失败,我将在第2点中描述.继续阅读.
另一种情况:试图通过某些API的两个opaque typedef(例如不相关域的GUID,或GUID和位域)重载,类型在语义上完全不同(所以 - 理论上 - 有效的重载)但实际上它们实际上是同样的事情 - 像无符号的int或void指针.
Java很简单,因为我们只有动态分配的对象.制造工厂同样简单:
class FooFactory {
public Foo createFooInSomeWay() {
// can be a static method as well,
// if we don't need the factory …Run Code Online (Sandbox Code Playgroud) 我刚收到一条评论,比如说
问题是手动内存管理.
delete在用户代码中没有位置,从C++ 14开始,也没有new
有人可以解释一下为什么吗?
这个问题要求在C++中实现静态工厂方法的简洁方法,这个答案描述了一种明确的方法.返回值优化将使我们免于制作不必要的副本Object,从而使这种方式创建Object与直接调用构造函数一样高效.复制i到id私有构造函数内部的开销可以忽略不计,因为它很小int.
但是,当Object包含一个实例变量Foo(它需要复杂的初始化逻辑)而不是一个小的基本类型时,问题和答案不会涵盖更复杂的情况.假设我想Foo使用传递给的参数构造Object.使用构造函数的解决方案看起来像:
class Object {
Foo foo;
public:
Object(const FooArg& fooArg) {
// Create foo using fooArg here
foo = ...
}
}
Run Code Online (Sandbox Code Playgroud)
使用类似于引用答案的静态工厂方法的替代方案将是,因为在我看来:
class Object {
Foo foo;
explicit Object(const Foo& foo_):
foo(foo_)
{
}
public:
static Object FromFooArg(const FooArg& fooArg) {
// Create foo using fooArg here
Foo foo = ...
return Object(foo);
}
}
Run Code Online (Sandbox Code Playgroud)
这里,复制foo_ …