Проблема в разработке программного обеспечения с использованием шаблона стратегии - PullRequest
0 голосов
/ 02 ноября 2019

В настоящее время я внедряю небольшую программу, я хочу эту программу для Mac OS и Window OS, поэтому я хочу использовать среду GLFW для Mac и Window API для среды Windows (я знаю, что GLFW является кроссплатформенным, но это не главное. .)

Моя проблема - проблема реализации проекта: я создал класс windowManager, который содержит экземпляр класса Window. Это Window содержит экземпляр объекта PatternWindow, где PatternWindow - интерфейс. У меня есть объект PatternGLFW3_VULKAN, который реализует PatternWindow. У этого PatternGLFW3_VULKAN есть член GLFWwindow * _window, и PatternGLFW3_VULKAN инициализирует _window с glfwCreateWindow(...).

class Window : public Singleton<Window>
{
public:
  somefunction(...)
  initializePatternWindow(unique_ptr<PatternWindow>&& patternWindow)
  unique_ptr<PatternWindow> getPatternWindow(){return _patternWindow;}

private:
  unique_ptr<PatternWindow> _patternWindow;
} 

class PatternWindow
{
public:
  PatternWindow();
  virtual ~PatternWindow();

  virtual void initialize() = 0;
  virtual void destroy   () = 0;

};



class PatternGLFW3_VULKAN : public PatternWindow
{
public:
  PatternGLFW3_VULKAN ();
  ~PatternGLFW3_VULKAN();

  virtual void initialize();
  virtual void destroy();

  const GLFWwindow& getWindow() const {return *_window;}

private:
  GLFWwindow * _window;
};

Мой вопрос о функции getWindow() в моем классе PatternGLFW3_VULKAN;как я могу создать виртуальную функцию getWindow() в моем классе PatternWindow, чтобы получить мое GLFWwindow* окно PatternGLFW3_VULKAN во время выполнения. Если я нахожусь в среде Mac OS, я могу создать виртуальную функцию GLFWwindow& getWindow() в моем PatternWindow, но если я запускаю свое программное обеспечение в среде Windows, введите GLFWwindow виртуальной функции getWindow() из patternWindow класс не будет правильным ...

Как я могу сделать, чтобы иметь виртуальный getWindow() в PatternWindow my, который возвращает GLFWwindow или экземпляр экрана Windows API во время выполнения?

РЕДАКТИРОВАТЬ:


class PatternWindow
{
public:
  PatternWindow();
  virtual ~PatternWindow();

  virtual void initialize() = 0;
  virtual void destroy   () = 0;
  virtual /*UNKNOW TYPE AT THE COMPILATION*/ getWindow() = 0;

};
/*UNKNOW TYPE AT THE COMPILATION*/

это моя проблема, я не знаю, как с ней справиться, для получения GLFWwindow *, когда я нахожусь в Mac OS и Windows для WindowsAPI, когда я компилирую в среде Windows ..

В основном цикле моего программного обеспечения нужно что-то подобное

int main(int argc, char** argv)
{
//initialisation of all my managers ans the data ect..

  while(!WindowClosed(Window::getPatternWindow()->getWindow()))
  {
    //DO SOME STUFF
  }
}

1 Ответ

2 голосов
/ 03 ноября 2019

Шаблон, к которому вы идете, может быть готов, но вы можете пожалеть об этом позже. Из вашей настройки я бы сделал вывод, что у вас есть две перегрузки WindowClosed() - одна с параметром GLFWwindow, а другая с параметром типа WinAPI. Первый будет использовать методы GLFW, чтобы определить, закрыто ли окно, а второй будет использовать Windows API. Одной из проблем является организация: сколько файлов содержат специфичные для GLFW методы? Может быть, у вас есть файл как с методами GLFW, так и с методами Win API? Это не обязательно неправильно, но это может быть боль в долгосрочной перспективе. Другая проблема состоит в том, что этот подход отличается от традиционного объектно-ориентированного подхода.

Тем не менее, давайте не будем заставлять вас идти одним путем из-за недостатка знаний. Чтобы этот подход работал, вы можете использовать препроцессор и typedef. При компиляции для Mac вы должны использовать строку типа typedef PatternGLFW3_VULKAN WindowType;. При компиляции для Windows вы должны использовать строку, определяющую WindowType как соответствующий тип Windows. Выбор между этими строками будет выполнен с помощью #ifdef WINDOWS (или любого другого условия, наиболее подходящего). Тогда можно объявить, что getWindow() возвращает WindowType.


Лучший подход (который вы реализовали в комментариях) - это перенести функциональность на объекты окна. Вместо function(object) используйте object.function(). Это требует больше виртуальных функций в вашем классе интерфейса, но есть преимущество в том, что у вас меньше файлов, которые зависят от ОС.

class PatternWindow
{
public:
  PatternWindow();
  virtual ~PatternWindow();

  virtual void initialize() = 0;
  virtual void destroy   () = 0;
  virtual bool closed    () = 0; // <-- New pure virtual function
};


class PatternGLFW3_VULKAN : public PatternWindow
{
public:
  PatternGLFW3_VULKAN ();
  ~PatternGLFW3_VULKAN();

  virtual void initialize();
  virtual void destroy();
  virtual bool closed();   // <-- OS-specific code is no longer in an extra file

private:
  GLFWwindow * _window;
};

Тогда в вашей основной функции вызов будет:

while(!Window::getPatternWindow()->closed())

Есть еще один шаг, который вы могли бы рассмотреть. (Соответственно, в вопросе недостаточно подробностей, чтобы определить, является ли этот вариант приемлемым.) Вам может не понадобиться полиморфизм для того, что вы пытаетесь сделать. Предположим, вы использовали следующее объявление:

class PatternWindow
{
#ifdef WINDOWS // Or whatever test is appropriate
    typedef PatternGLFW3_VULKAN * WindowType;
#else
    typedef /* Windows API type */ WindowType;
#endif
public:
  PatternWindow();
  ~PatternWindow();

  void initialize();
  void destroy   ();
  bool closed    ();

private:
    WindowType _window;
};

Этот интерфейс больше не поддерживает полиморфизм. Это плохо? Вам нужно несколько классов, производных от PatternWindow в одной операционной системе ? Возможно нет. Вот потенциальный файл реализации для этого класса.

#include "PatternWindow.h"

#ifdef WINDOWS // Or whatever test is appropriate
#include "PatternWinAPI.src"  // <-- File with an implementation based on Win API 
#else
#include "PatternGLFW.src"    // <-- File with an implementation based on GLFW
#endif

Если вам не нравится расширение .src, используйте что-то еще. Только не делайте эти файлы похожими на что-то для самостоятельной компиляции. Каждый файл будет иметь реализацию, соответствующую используемому им API. Например, PatternGLFW.src может содержать определение функции, подобное следующему:

void PatternWindow::initialize()
{
    _window = glfwCreateWindow(...);
    // Etc.
}

Это устраняет издержки полиморфизма и, по-видимому, не создает бремени кодирования. Кроме того, вам не нужно отслеживать, какие файлы нужны для каких операционных систем (более простая настройка сборки). Однако организация PatternWindow.cpp встречается редко.

...