我一直在Wikipedia查看示例C ++ Factory方法模式,并提出了几个问题:
由于工厂方法是静态的,这是否意味着新创建的对象不会超出范围并且在工厂方法退出时调用析构函数方法?
为什么返回指针而不是引用?这是严格意义上的问题,还是其中一个重要原因?
编辑:我想的越多,引用和返回的指针都将保留在范围内,因为它们是在方法之外引用的。因此,不会在任何一个上调用析构函数。所以这是一个偏好问题。否?
edit2:我在返回的引用上打印出析构函数调用,并且在程序退出之前不会打印。所以,除非有进一步的反馈,我现在就去参考。这样我就可以使用“。”返回对象上的运算符。
答案 0 :(得分:7)
静态方法是可以在没有工厂实例的情况下调用的方法。这与新创建的对象的生命周期无关。您可以使用具有相同成功的非静态方法。工厂方法通常不需要来自同一类的现有对象的任何数据,因此不需要现有实例,这就是为什么因果方法通常是静态的。
您将使用 new 创建工厂将返回的对象。通常用指针返回它们。这明确表明它是一个新的对象,而调用者必须关注它的生命周期。
答案 1 :(得分:7)
我认为理解内存管理存在更大的问题。工厂方法是在堆上分配项目(使用new)。堆上的项永远不会自动回收(除了过程终止时的现代桌面操作系统)。您描述的行为是堆栈中的项目,当您离开本地范围时,它们将被回收。
答案 2 :(得分:3)
如果返回对对象的引用,则当方法超出范围时引用将变为无效。指针不会发生这种情况,因为不会调用析构函数。
当值超出范围时,静态修改,但仅当变量声明为static时才会修改,而不是在方法声明为静态时。
答案 3 :(得分:3)
您的Wiki链接说错了。
不应该有任何静态方法。您可以将Factory Method视为创建对象的模板方法模式。此方法不接收任何“Name”参数,并始终创建相同类型的对象。
通常,设计开始使用Factory 方法(不太复杂,更多 可定制的,子类扩散) 并向抽象工厂发展, 原型或Builder(更灵活, 更复杂)作为设计师 发现更灵活的地方 需要。 [GoF,p136]
在以下示例中,Business::makeObject
是工厂方法
class ObjectBase
{
public:
virtual void action() = 0;
virtual ~ObjectBase(){};
};
class ObjectFirst : public ObjectBase
{
public:
virtual void action(){ std::cout << "First"; }
};
class ObjectSecond : public ObjectBase
{
public:
virtual void action(){ std::cout << "Second"; }
};
class Business
{
public:
void SendReport()
{
std::auto_ptr< ObjectBase > object(makeObject());
object->action();
}
virtual ~Business() { }
protected:
virtual ObjectBase* makeObject() = 0;
};
class BusinessOne: public Business
{
public:
protected:
virtual ObjectBase* makeObject()
{
return new ObjectFirst();
}
};
class BusinessTwo: public Business
{
public:
protected:
virtual ObjectBase* makeObject()
{
return new ObjectSecond();
}
};
int main()
{
std::auto_ptr<Business> business( new BusinessTwo() );
business->SendReport();
return 0;
}
答案 4 :(得分:1)
修改强>
我认为维基百科 - 在c ++示例中是错误的
我们有exmaple - 与类图或此处(http://www.apwebco.com/gofpatterns/creational/FactoryMethod.html)
如果您阅读来自最受信任的来源的模式会更好,例如:设计模式:可重复使用的面向对象软件的元素。
答案 5 :(得分:-1)
关键字static表示方法和变量上的不同内容。在示例中的方法上,它意味着它是类全局的,并且您不需要该类的实例来调用它。
要动态创建新对象,您需要使用new,或者“技巧”是将临时对象分配给引用。将临时对象分配给某个点不会使该对象保持活动状态。
所以你可以做到以下几点,但通常不会这样做,因为你经常想要保留从工厂创建的许多东西,然后你必须复制它们而不是简单地将指针放在列表中。
class PizzaFactory {
public:
static Pizza& create_pizza(const std::string& type) {
if (type == "Ham and Mushroom")
return HamAndMushroomPizza();
else if (type == "Hawaiian")
return HawaiianPizza();
else
return DeluxePizza();
}
};
const Pizza &one = create_pizza(""); // by ref
Pizza two = create_pizza(""); // copied
修改的 对不起代码中的错误 - 将ref缺少const添加到ref。
通常,临时对象只会持续到它出现的完整表达式的结尾。但是,C ++故意指定将临时对象绑定到堆栈上对const的引用会延长临时对象到引用本身生命周期的生命周期