C+中的通用工厂+; 我正在研究一个游戏,我试图通过分析一个文本文件来实现一个聪明的方法来创建C++中的NPC对象。
目前,这是在Factory对象中硬编码的。像这样:C+中的通用工厂+; 我正在研究一个游戏,我试图通过分析一个文本文件来实现一个聪明的方法来创建C++中的NPC对象。,c++,factory,C++,Factory,目前,这是在Factory对象中硬编码的。像这样: IActor * ActorFactory::create(string actortype, Room * r, string name, int hp) { if(actortype == "Troll") { return new Troll(r, name, hp); } if (actortype == "Dragon") { return new Dragon(
IActor * ActorFactory::create(string actortype, Room * r, string name, int hp)
{
if(actortype == "Troll")
{
return new Troll(r, name, hp);
}
if (actortype == "Dragon")
{
return new Dragon(r, name, hp);
}
// ... and so on
throw "Can't recognize type '"+actortype+"'.";
}
在我看来,这是一种非常丑陋的做法。因为它(除其他外)打破了传统
我学的是Java,在Java中,我会做一些事情,比如让每个IActor在程序执行开始时向ActorFactory报告它的类名和类类型。然后,工厂将关系存储在一个映射中,然后可以轻松地查找哪些字符串映射到哪个对象,然后可以轻松地实例化它
编辑:我还希望能够使用可变数量/类型的参数调用构造函数
<>强> C++中如何做到这一点?可以这样做吗?您可以使用映射来存储返回Actor*的函数指针,该指针是指向所创建对象的指针。那么代码就是
std::map<std::string,IActor* (*) (Room*,std::string,int)> constructorMap
constructorMap["Troll"]=&TrollConstructor
//etc...
IACtor* ActorFactory::create(string actortype,Room* r,string name,int hp){
return (*constructorMap[actortype])(r,name,hp);
}
std::映射构造函数映射
constructorMap[“Troll”]=&TrollConstructor
//等等。。。
IACtor*ActorFactory::create(字符串actortype,房间*r,字符串名称,int-hp){
return(*constructorMap[actortype])(r,name,hp);
}
< P>(请原谅我用函数指针做的任何错误,它们不是我的优点)C++中的< P>,你通常会使用抽象工厂设计模式。 要点是:“关于要创建的参与者类型的决定不应该由
ActorFactory::create()
负责”。在您的情况下,此方法不应该基于字符串决定实例化哪个类,而应该依赖于类型;此类型是实际的factory类
TrollFactory
,DragonFactory
,等等。这些工厂类派生自一个基类ActorFactory2
(后面的2是因为ActorFactory
)create()
方法,而无需参数返回指向新创建的actor类的指针ActorFactory::create()
接受一个指向从ActorFactory2
派生的对象的指针,并调用ActorFactory2::create()
方法:它将使用适当的参数创建请求的actor,而不使用switch语句
class ActorFactory2
{
string m_name; // Each IA actor has a name
int m_hp; // and some HP
public:
ActorFactory2( const string &p_name, int p_hp )
: m_name( p_name ), m_hp( p_hp ) {}
virtual IActor * create() const = 0;
};
class TrollFactory : public ActorFactory2
{
// No special argument needed for Troll
public:
TrollFactory( const string &p_name, int p_hp )
: ActorFactory2( p_name, p_hp ) {}
virtual IActor * create() const { return new Troll( m_name, m_hp ); }
};
class DragonFactory : public ActorFactory2
{
FlameType m_flame; // Need to indicate type of flame a dragon spits
public:
DragonFactory( const string &p_name, int p_hp, const FlameType &p_flame )
: ActorFactory2( p_name, p_hp )
, m_flame( p_flame ) {}
virtual IActor * create() const { return new Dragon( m_name, m_hp, m_flame ); }
};
IActor * ActorFactory::create( const ActorFactory2 *factory )
{
return factory->create();
}
int main( int, char ** )
{
ActorFactory af;
...
// Create a dragon with a factory class instead of a string
ActorFactory2 *dragonFactory = new DragonFactory( "Fred", 100, RedFlames );
IActor *actor = af.create( dragonFactory ); // Instead of af.create( "dragon", ... )
delete dragonFactory;
}
我在另一个关于C++工厂的问题上回答了问题。请看是否有兴趣建立一个灵活的工厂。我试图描述一种从ET++到使用宏的老方法,这种方法对我来说非常有效
是将旧Mac App移植到C++和X11的项目。在it的努力中,Eric Gamma等开始考虑设计模式,具体术语是:参数化工厂方法,它是工厂方法设计模式的一部分
要使用泛型工厂,请将类保存在映射中并通过字符串进行访问。如果类名可用,请使用“typeid(MyClass).name()将该类注册到工厂,并通过提供clone()成员函数返回该类的副本 但是,对于简单的不可扩展工厂,我使用您问题中的方法我无法回答您关于传递更多变量参数的问题,但要进行反序列化,只需将部分传递给类并让它自己进行反序列化就足够了(您似乎已经这样做了)。感谢您的回答,但这不允许我有一个变量参数列表。(不同数量的参数和不同类型)这是有道理的,但会生成很多类(如果有很多参与者)优点是您可以将变量的变量传递给CtoR。我不知道工厂方法或抽象工厂模式有很多不同。因为在使用之前,我们仍然需要知道具体的类。在我的例子中,我需要基于配置文件中的名称实例化我的类。菲尼特正是我想要的。