В настоящее время я работаю над своим собственным движком, в частности графическим интерфейсом, и пытаюсь сделать так, чтобы он мог выбирать между DirectX и openGL рендерингом. Для этой цели я хочу иметь синглтон Менеджера текстур (я привык использовать стандартную реализацию этого). Однако в этом случае я хочу иметь возможность выбирать динамический тип экземпляра при абстрагировании функциональности. Вот моя реализация до сих пор:
template <typename T>
class TextureManagerType
{
public:
virtual ~TextureManagerType() = 0 {}T* GetTexture(TEXTURE_ID texID)
{
std::map<TEXTURE_ID, T*>::const_iterator it = m_textures.find(texID);
if(it != m_textures.end())
{
return (*it)->second;
}
else
{
assert(0);
return 0;
}
}
bool Load(const std::string& texturePaths)
{
File f;
if(!f.Open(texturePaths))
{
ReportError("Fatal error! Could not open: " + texturePaths);
return false;
}
std::string str;
while(!f.EndOf())
{
if(!f.GetString(&str))
{
ReportError("Warning: Unexpected end of file in texturepaths file: " + texturePaths);
}
LoadTexture(str);
}
return true;
}
virtual T* LoadTexture(const std::string& texturePath) = 0;
protected:
std::map<TEXTURE_ID, T*> m_textures;
};//Uncopyable is a base class with a disabled copy constructor
class TextureManager : public Uncopyable
{
private:
TheTextureManager();
public:
//T here is underlined in all three mentions as it is undefined
static TextureManagerType<T>* Instance()
{
return m_pInstance;
}
static void SetDynamicType(TextureManagerType<T>* type)
{
m_pInstance = type;
}
static TextureManagerType<T>* m_pInstance;//static TexManagerType* Instance()
//{
// return m_pInstance;
//}
//static void SetDynamicType(TexManagerType* type)
//{
// m_pInstance = type;
//}
//static TexManagerType* m_pInstance;
};
//Named to be consistent with normal singletons
typedef TextureManager TheTextureManager;
Как вы можете видеть, я пожертвовал бонусом RAII синглтона и мне нужно инициализировать указатель m_pInstance на ноль.
//I want the singleton once set, to be able to be accessed thusly:
TheTextureManager::Instance()->DoTextureFunction();
Я не хочу синглтона для каждого типа TextureManager, так как я хотел бы иметь возможность контролировать срок службы каждого производного менеджера при сохранении глобальной доступности.
В настоящее время моя система НЕ работает вообще, поскольку возвращаемый тип для TextureManager :: Instance требует знания шаблонного типа, который недоступен.
Я пытался вложить TextureManagerType в TextureManager, но это означало, что каждый вызов
диспетчеру текстур понадобится требуемый тип в качестве параметра шаблона, который в некотором роде лишает смысла абстрагировать это.
Пожалуйста, помогите парням и девушкам и будьте конструктивны в своих комментариях.
Пожалуйста, задавайте вопросы, если я пропустил важные / все детали. Мозг слишком устал, чтобы думать прямо сейчас.
Спасибо
Вы можете определить абстрактный, не шаблонный интерфейс для вашего TextureManagerType
и используйте это для ссылки на реализацию менеджера текстур из одноэлементного объекта менеджера текстур.
Для этого вам также понадобится полиморфное представление для ваших объектов Texture, которое может быть чем-то простым, например, объединяющим типом или абстрактным базовым классом, с производными классами для различных конкретных типов текстур.
Все может выглядеть примерно так:
union TextureContainer {
OpenGLTexture* oglt;
DirectXTexture* dxt;
};
class TextureManagerTypeBase
{
public:
virtual ~TextureManagerType() = 0;
virtual TextureContainer GetTexture(TEXTURE_ID texID) = 0;
virtual TextureContainer LoadTexture(const std::string& texturePath) = 0;
//this looks like it only refers to other public
// methods, so it's staying here
virtual bool Load(const std::string& texturePaths)
{
...
}
};
template <typename T>
class TextureManagerType : public TextureManagerTypeBase
{
public:
// pretty much the same as before
// minus Load wich is defined in the base class
// plus wrapping T into a TextureContainer
...
};//Uncopyable is a base class with a disabled copy constructor
class TextureManager : public Uncopyable
{
private:
TheTextureManager();
public:
//T here is underlined in all three mentions as it is undefined
static TextureManagerTypeBase* Instance()
{
return m_pInstance;
}
static void SetDynamicType(TextureManagerTypeBase* type)
{
m_pInstance = type;
}
static TextureManagerTypeBase* m_pInstance;
};
Это немного грубо, но, надеюсь, вы поняли идею.
Других решений пока нет …