c++ factory pattern component creator with singleton container

1.1k Views Asked by At

I'm implementing the factory pattern for component creation and want to implement a singleton container for all instances of each type created by the factory. Ideally this would be one vector for each type created in the factory.

This would be really easy if I could keep base class pointers in the vector, but alas my use case would vastly prefer all the instances be stored contiguously instead of wherever new puts them to get as many cache hits as possible.

I was thinking about doing something like this for the factory map:

Map<string,pair<constructorFnPtr, vector<baseClass>>

This has the issue of losing the data from the derived class as it is cast to the base class.

I was also thinking that a pointer to a vector as the second member of the pair would be a good way to do it, but I'm not sure how that could be implemented while still having a different data type stored in each vector. I don't think this would be possible since the templated vectors are all technically different classes.

Is there any way to do what I'm trying to do? I've been trying to figure something out for the past couple days with no luck.

Alternatively if there is another good way to store the vectors (ie as a static member of the component class) I'm open to any suggestions like that as well!

2

There are 2 best solutions below

4
On

You can't do this with a std::vector of contiguous objects.

The reason is: a factory is supposed to build objects, and then return a pointer to them. The problem is that the pointer is going to be stored around in your application, while the next call to your_vector.push_back() is likely going to invalidate them, as the C++ documentation says:

If the new size() is greater than capacity() then all iterators and references (including the past-the-end iterator) are invalidated. Otherwise only the past-the-end iterator is invalidated.

So, your next call to the factory can invalidate all your previous calls.

2
On

I wouldn't consider using the factory pattern for components but rather the object pool pattern since you will likely want to use the factory pattern for managing the creation of entities instead.

I use a base Component class for all components. This allows me to be able to manage some static run-time type information for each component and expose a set of common methods. I then implemented an interface IComponentPool that is the contract for my component object pool. Then I defined a templated class ComponentPool<T> that is derived from IComponentPool. Inside this template class is where I manage two vectors/arrays. Then there is a ComponentPoolMap that exposes some map-like behavior to lookup a ComponentPool<T> based on component types.

Now in the ComponentPool<T> class, the first array is a sparse array used as a lookup. It holds an index offset to where the component resides inside the second dense packed array. The sparse array could simply be a means to take an EntityId and convert it to where component resides. A more sophisticated handle system can be easily implemented top of this type of framework if you want.

The idea here is that the packed dense acts as your contiguous memory buffer that you can easily iterate in a cache friendly manor in tight loops but the sparse array provides a single-level of indirection lookup on a per entity basis for components.

Now the factory pattern is where you create your Entity or EntityId handle to an entity and create all the necessary aspects that make up an Orc, Zombie, or whatever for your game. The factory acts as a layer that sits on top of your game object system of which your ComponentPoolMap is likely only a small slice of that system.