У меня есть следующая проблема в архитектуре приложения, и я хочу ее решить (извините за большой объем текста).
Я создаю прототип игрового движка, и у меня есть базовая аннотацияclass AbstractRenderer
(я буду использовать синтаксис C ++, но проблема по-прежнему общая).
Предположим, что есть некоторые производные реализации этого рендерера, скажем, DirectxRenderer
иOpenglRenderer
.
Теперь предположим, что только один из этих средств визуализации (давайте придерживаться DirectX) имеет член с именем IDirect3D9Device* m_device;
Очевидно, что в этот момент все в порядке - m_device
используется внутри DirectxRenderer
и не должен быть представлен в абстрактном суперклассе AbstractRenderer
.
Я также добавляю некоторый абстрактный интерфейс рендеринга, например IRenderable
.Это означает просто один чисто виртуальный метод virtual void Render(AbstractRenderer* renderer) const = 0;
И это то место, где начинаются некоторые проблемы.Предположим, я моделирую какую-то сцену, поэтому в этой сцене, вероятно, будут некоторые геометрические объекты.
Я создаю абстрактный суперкласс AbstractGeometricalObject
и производную реализацию на основе DirectX DirectxGeometricalObject
.Второй будет отвечать за хранение указателей на специфичные для DirectX буферы вершин и индексов.
Теперь - проблема.
AbstractGeometricalObject
должно, очевидно, получить IRenderable
интерфейс, потому что это рендеринг в логическом смысле.
Если я получу DirectxGeometricalObject
из AbstractGeometricalObject
, первый должен иметь метод virtual void Render(AbstractRenderer* renderer) const { ... }
, и этот материал Abstract...
приносит некоторые проблемы.
См.код для лучшего объяснения:
А сейчас мои занятия выглядят следующим образом:
class AbstractGeometricalObject : public IRenderable {
virtual void Render(AbstractRenderer* renderer) const { ... }
};
class DirectxGeometricalObject : public AbstractGeometricalObject {
virtual void Render(AbstractRenderer* renderer) const {
// I think it's ok to assume that in 99 / 100 cases the renderer
// would be a valid DirectxRenderer object
// Assume that rendering a DirectxGeometricalObject requires
// the renderer to be a DirectxRenderer, but not an AbstractRenderer
// (it could utilize some DX-specific settings, class members, etc
// This means that I would have to ***downcast*** here and this seems really
// bad to me, because it means that this architecture sucks
renderer = dynamic_cast<DirectxRenderer*>(renderer);
// Use the DirectX capabilities, that's can't be taken out
// to the AbstractRenderer superclass
renderer.DirectxSpecificFoo(...);
}
Я знаю, что, вероятно, слишком беспокоюсь, но это удручаетв таком простом случае означает, что меня могут заставить делать много откликов в случае роста моего приложения.
Определенно, я бы хотел избежать этого, поэтому, пожалуйста, не могли бы выпосоветуйте мне что-нибудь лучше с точки зрения дизайна / укажите мои ошибки.
Спасибо