使用策略模式设计软件的问题
Problem in designing software using strategy pattern
我目前正在实施一个小软件,我希望这个软件在 Mac OS 和 Window OS 上工作,所以我想在 [=67] 上使用 GLFW =] 环境和 Window API 用于 Windows 环境(我知道 GLFW 是跨平台的,但这不是重点..)
我的问题是设计实现问题:
我创建了一个 windowManager
class 来保存 Window
class 的一个实例。 Window
保留一个对象的实例,该对象是 PatternWindow
,其中 PatternWindow
是一个接口。我有一个实现 PatternWindow
的对象 PatternGLFW3_VULKAN
。这个 PatternGLFW3_VULKAN
有一个成员 GLFWwindow * _window
,并且 PatternGLFW3_VULKAN
用 glfwCreateWindow(...)
.
初始化 _window
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;
};
我的问题是关于 PatternGLFW3_VULKAN
class 中的 getWindow()
函数;我如何在 PatternWindow
class 中创建虚拟 getWindow()
函数,以便在 [=80] 处获得 PatternGLFW3_VULKAN
的 GLFWwindow*
window =] 时间。如果我在 Mac OS 环境中,我可以在我的 PatternWindow
中创建一个虚函数 GLFWwindow& getWindow()
,但是如果我 运行 我的软件在 [=76] =]环境,patternWindow
class的虚函数getWindow()
的类型GLFWwindow
不正确...
如何在 PatternWindow
我的 returns GLFWwindow
或 Windows [=59] 中拥有一个虚拟 getWindow()
=] 屏幕在 运行 时间?
编辑:
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*/
是我的问题,我不知道如何处理它,因为当我在 Mac OS 和 Windows 实例中时获得 GLFWwindow*当我在 Windows 环境中编译时 windows API..
在我的软件的主循环中想要这样的东西
int main(int argc, char** argv)
{
//initialisation of all my managers ans the data ect..
while(!WindowClosed(Window::getPatternWindow()->getWindow()))
{
//DO SOME STUFF
}
}
你的方向是可以做到的,但你以后可能会后悔。我会从你的设置中推断出你有两个 WindowClosed()
的重载——一个的参数是 GLFWwindow
,另一个的参数是 WinAPI 类型。前者会使用 GLFW 方法来检测 window 是否关闭,而后者会使用 Windows API。一个问题是组织之一:有多少文件包含 GLFW 特定的方法?也许您甚至有一个同时包含 GLFW 方法和 Win API 方法的文件?这不一定是错误的,但在漫长的 运行 中可能会很痛苦。另一个问题是这种方法与传统的面向对象方法不同。
不过,我们不要因为缺乏知识而强迫您走一条路。要使这种方法起作用,您可以使用预处理器和 typedef
。如果为 Mac 编译,您将使用像 typedef PatternGLFW3_VULKAN WindowType;
这样的行。如果针对 Windows 进行编译,您将使用一行将 WindowType
定义为相应的 Windows 类型。在这些行之间进行选择将通过 #ifdef WINDOWS
(或任何最合适的条件)来完成。然后 getWindow()
可以声明为 return WindowType
.
更好的方法(您在评论中意识到)是将功能转移到 window 对象。使用 object.function()
而不是 function(object)
。这需要在您的界面 class 中使用更多的虚函数,但好处是您的 OS 特定文件较少。
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
派生多个classes?也许不是。这是此 class.
的潜在实现文件
#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
的组织并不常见。
我目前正在实施一个小软件,我希望这个软件在 Mac OS 和 Window OS 上工作,所以我想在 [=67] 上使用 GLFW =] 环境和 Window API 用于 Windows 环境(我知道 GLFW 是跨平台的,但这不是重点..)
我的问题是设计实现问题:
我创建了一个 windowManager
class 来保存 Window
class 的一个实例。 Window
保留一个对象的实例,该对象是 PatternWindow
,其中 PatternWindow
是一个接口。我有一个实现 PatternWindow
的对象 PatternGLFW3_VULKAN
。这个 PatternGLFW3_VULKAN
有一个成员 GLFWwindow * _window
,并且 PatternGLFW3_VULKAN
用 glfwCreateWindow(...)
.
_window
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;
};
我的问题是关于 PatternGLFW3_VULKAN
class 中的 getWindow()
函数;我如何在 PatternWindow
class 中创建虚拟 getWindow()
函数,以便在 [=80] 处获得 PatternGLFW3_VULKAN
的 GLFWwindow*
window =] 时间。如果我在 Mac OS 环境中,我可以在我的 PatternWindow
中创建一个虚函数 GLFWwindow& getWindow()
,但是如果我 运行 我的软件在 [=76] =]环境,patternWindow
class的虚函数getWindow()
的类型GLFWwindow
不正确...
如何在 PatternWindow
我的 returns GLFWwindow
或 Windows [=59] 中拥有一个虚拟 getWindow()
=] 屏幕在 运行 时间?
编辑:
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*/
是我的问题,我不知道如何处理它,因为当我在 Mac OS 和 Windows 实例中时获得 GLFWwindow*当我在 Windows 环境中编译时 windows API..
在我的软件的主循环中想要这样的东西
int main(int argc, char** argv)
{
//initialisation of all my managers ans the data ect..
while(!WindowClosed(Window::getPatternWindow()->getWindow()))
{
//DO SOME STUFF
}
}
你的方向是可以做到的,但你以后可能会后悔。我会从你的设置中推断出你有两个 WindowClosed()
的重载——一个的参数是 GLFWwindow
,另一个的参数是 WinAPI 类型。前者会使用 GLFW 方法来检测 window 是否关闭,而后者会使用 Windows API。一个问题是组织之一:有多少文件包含 GLFW 特定的方法?也许您甚至有一个同时包含 GLFW 方法和 Win API 方法的文件?这不一定是错误的,但在漫长的 运行 中可能会很痛苦。另一个问题是这种方法与传统的面向对象方法不同。
不过,我们不要因为缺乏知识而强迫您走一条路。要使这种方法起作用,您可以使用预处理器和 typedef
。如果为 Mac 编译,您将使用像 typedef PatternGLFW3_VULKAN WindowType;
这样的行。如果针对 Windows 进行编译,您将使用一行将 WindowType
定义为相应的 Windows 类型。在这些行之间进行选择将通过 #ifdef WINDOWS
(或任何最合适的条件)来完成。然后 getWindow()
可以声明为 return WindowType
.
更好的方法(您在评论中意识到)是将功能转移到 window 对象。使用 object.function()
而不是 function(object)
。这需要在您的界面 class 中使用更多的虚函数,但好处是您的 OS 特定文件较少。
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
派生多个classes?也许不是。这是此 class.
#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
的组织并不常见。