模板化抽象工厂类与池

时间:2011-03-24 01:26:01

标签: c++ object factory

我正在研究处理事件的游戏引擎组件。我要做的是创建一个系统,我可以按名称注册新的事件类型。然后事件管理器将保存事件类型和工厂的集合以生成这样的事件类型但是我想使它使用池化系统,以便我创建一个事件,使用它然后而不是删除它,把它扔进一个清单。下次我创建该事件,而不是使用堆,我可以从池中分配。

给定这些事件类型的层次结构......

struct TEvent
{
  int nID;
  int nTimeStamp;
};

struct TCollisionEvent : public TEvent
{
  TEntity* pEntity1;
  TEntity* pEntity2;
  Vector3* pvecPoint;
};

然后,我创建了一个智能工厂,用于执行此创建/重新打印操作:

template <class BASE_CLASS>
class CSmartFactory
{
private:
  typedef typename std::list<BASE_CLASS*> TBaseList;
  typedef typename std::list<BASE_CLASS*>::iterator TBaseListItr;

  TBaseList* m_plstPool;

public:
  explicit CSmartFactory()
  {
    m_plstPool = NULL;
  }

  ~CSmartFactory()
  {
    TBaseListItr itr;

    if (m_plstPool)
    {
      for (itr = m_plstPool->begin(); itr != m_plstPool->end(); itr++)
      {
        BASE_CLASS* pEntity = *itr;
        SAFE_DELETE(pEntity);
      }

      m_plstPool->clear();
      SAFE_DELETE(m_plstPool);
    }    
  }

  bool Init(int nPoolSize)
  {
    bool bReturn = false;

    do 
    { 
      m_plstPool = new TBaseList;
      IwAssert(MAIN, m_plstPool);

      while (nPoolSize--)
      {
        BASE_CLASS* pBaseObject = new BASE_CLASS;
        IwAssert(MAIN, pBaseObject);

        m_plstPool->push_back(pBaseObject);
      }

      bReturn = true;
    } while(0); 

    return bReturn; 
  }

  BASE_CLASS* Create()
  {
    BASE_CLASS* pBaseObject = NULL;

    //
    // grab a pre-made entity from the pool or allocate a new one
    if (m_plstPool->size() > 0)
    {
      pBaseObject = m_plstPool->front();
      m_plstPool->pop_front();
      pBaseObject->Clear();
    }
    else
    {
      pBaseObject = new BASE_CLASS;
      IwAssert(MAIN, pBaseObject);
    }

    return pBaseObject;
  }

  void Recycle(BASE_CLASS* pBaseObject)
  {
    m_plstPool->push_back(pBaseObject);
  }
};

现在我可以这样做:

CSmartFactory<TCollisionEvent>* pCollisionEventFactory = new CSmartFactory<TCollisionEvent>;

但我想做的是让我的事件管理员允许进行动态事件注册,但这就是我遇到麻烦的地方。

理想情况下,RegisterEvent将跟踪stl :: map中的名称和工厂指针,但不太确定如何到达那一点。也许我完全走错了路。

这个编译

class TEventManager
{
public:
  TEventManager();
  ~TEventManager();

  bool RegisterEvent(char* pszEventName, CSmartFactory<TEvent>* pFactory);
};

直到你添加

TEventManager::RegisterEvent("CollisionEvent", new CSmartFactory<TEntityCollisionEvent>);

所以现在我绝望地试图找到一种方法来使这一切工作。

有人在这里有一些想法吗?

佛瑞德

3 个答案:

答案 0 :(得分:0)

我假设您想重用事件以避免昂贵的堆malloc / free?

我认为这里正确的答案不是通过编写自己的重用对象结构来卷积代码,而是使用小对象分配器。首先,可能值得研究boost::pool

答案 1 :(得分:0)

这两个类CSmartFactory<TEntityCollisionEvent>CSmartFactory<TEvent>将生成类似

的内容
  • CSmartFactory_TEntityCollisionEvent

  • CSmartFactory_TEvent

它们实际上是两个独立且无关的类。试图互换使用它们是不明智的,虽然它们的行为相同(它们的类型类是多态的)。

动态施法不会起作用,但你可以尝试使用强力施法:

TEventManager::RegisterEvent("CollisionEvent", 
        reinterpret_cast<CSmartFactory<TEvent>*>(new CSmartFactory<TEntityCollisionEvent>));

警告:风险自负! ; - )

答案 2 :(得分:0)

好的,所以在经过大量的敲击之后,我意识到解决方案比我想要的更简单。

所有经理都应该关心管理TEvent *。每个TEvent都有一个唯一的哈希值,使其独一无二,因此当添加一个新事件时,它的字符串名称和哈希名称都会被存储。所以,从那里我可以添加一个指向任何子类的指针,只要它被转换为TEvent。

我让它变得比它需要的更复杂。