c++ - C++ 中的通用工厂

标签 c++ factory

<分区>

我正在开发一款游戏,并尝试实现一种通过解析文本文件在 C++ 中创建 NPC 对象的智能方法。

目前这是硬编码在工厂对象中。像这样:

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+"'.";
}

在我看来,这是一种非常丑陋的方式。因为它(除其他外)打破了 Open/Closed principle .

我受过 Java 教育,在 Java 中我会做一些事情,比如让每个 IActor 在程序执行开始时向 ActorFactory 报告它的类名和类类型。然后,工厂会将关系存储在映射中,然后可以轻松地查找哪个字符串映射到哪个对象,然后可以轻松地实例化它。

编辑:我还希望能够使用可变数量/类型的参数调用构造函数。

这在 C++ 中如何完成?可以吗?

最佳答案

在 C++ 中,您通常会使用抽象工厂设计模式。

要点是:“关于要创建的 actor 类型的决定不应由 ActorFactory::create() 负责。”在您的情况下,此方法不应根据字符串决定实例化哪个类,而应依赖类型;此类型实际的工厂类。

  1. 每个 actor 类都有自己的工厂类:TrollFactoryDragonFactory 等,派生自基类 ActorFactory2(尾随2 因为 ActoryFactory 已经被占用);

  2. 每个专门的工厂类都实现了一个虚拟的 create() 方法,没有参数返回指向新创建的 actor 类的指针;

  3. 如果您需要参数来构造一个 actor,请在创建 actor 之前将它们传递给工厂对象:将它们传递到 ctor 中并将它们存储为成员变量; create() 将在稍后创建 actor 时检索它们;

  4. 这样,您可以轻松地为不同的参与者传递不同的参数,并且您的工厂机制将是可扩展的(向开放/封闭原则迈出的一步);

  5. 现在,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++ - C++ 中的通用工厂,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1741178/

相关文章:

c++ - ezpwd reed-solomon纠错库使用方法

c++ - 强制所有符号从链接的 lib 文件导出到 DLL

c++ - GlowCode 与 AQTime C++ 现实世界中的分析性能对比?

c++ - CRTP 自动注册工厂(静态初始化顺序失败)

java - 如何以正确的方式创建一个具有多种用途的对象?

c++ - 将 POD 结构转换为派生类型

c# - Autofac:在泛型方法中解析泛型接口(interface)

c# - 具有通用存储库的 Activator.CreateInstance

c# - 工厂方法还是其他模式?

c++ - 片段着色器中设置的颜色未显示 GLSL 1.30