C++ 设计模式:C++;抽象层
我试图编写一个抽象层,让我的代码在不同的平台上运行。让我举一个我最终希望在高级代码中使用的两个类的例子:C++ 设计模式:C++;抽象层,c++,c,abstraction,hal,C++,C,Abstraction,Hal,我试图编写一个抽象层,让我的代码在不同的平台上运行。让我举一个我最终希望在高级代码中使用的两个类的例子: class Thread { public: Thread(); virtual ~Thread(); void start(); void stop(); virtual void callback() = 0; }; class Display { public: static void drawText(const char* t
class Thread
{
public:
Thread();
virtual ~Thread();
void start();
void stop();
virtual void callback() = 0;
};
class Display
{
public:
static void drawText(const char* text);
};
我的问题是:我可以使用什么设计模式让低级代码填充实现?
以下是我的想法以及为什么我认为它们不是一个好的解决方案:
highLevel/thread.h
中,将特定于平台的实现放在lowLevel/platformA/thread.cpp中是没有问题的。这是一个低开销的解决方案,可在链接时解决。唯一的问题是,低级实现不能向其中添加任何成员变量或成员函数。这使得某些事情无法实施
类线程
纯虚拟,并通过继承实现底层功能。高级代码可以通过调用如下工厂函数来访问低级实现:
// thread.h, below the pure virtual class definition
extern "C" void* makeNewThread();
// in lowlevel/platformA/thread.h
class ThreadImpl: public Thread
{ ... };
// in lowLevel/platformA/thread.cpp
extern "C" void* makeNewThread() { return new ThreadImpl(); }
这将足够整洁,但对于静态类来说是失败的。我的抽象层将用于硬件和IO,我真的希望能够使用Display::drawText(…)
,而不是携带指向单个Display
类的指针extern“C”handle\u t createThread()
。这对于访问只存在一次的低级硬件(如显示器)来说是非常容易的。但是对于任何可能多次出现的东西(锁、线程、内存管理),我必须在我的高级代码中携带句柄,这很难看,或者有一个隐藏句柄的高级包装类。无论哪种方式,我都需要将句柄与高级别和低级别侧的相应功能相关联extern“C”
函数用于只存在一次的低级内容。工厂功能(见3)中可以多次出现的内容。但我担心混合的东西会导致不一致、不可读的代码我非常感谢您为设计符合我要求的模式提供的提示。您不需要有平台无关的基类,因为您的代码一次只针对一个具体的平台进行编译 只需将include路径设置为,例如,
-Iinclude/generic-Iinclude/platform
,并在每个受支持平台的include目录中有一个单独的线程类
您可以(也应该)编写默认编译和执行的平台无关测试,以确认不同的平台特定实现遵循相同的接口和语义
另外,正如StoryTeller所说,线程是一个坏例子,因为已经有了一个可移植的std::Thread
。我假设您确实需要抽象一些其他特定于平台的细节
PPS。您仍然需要找出通用(与平台无关)代码和特定于平台的代码之间的正确划分:没有什么灵丹妙药来决定要做什么,只是在重用/复制、简单代码和高度参数化代码之间进行一系列权衡,等等。您似乎想要为
线程
类添加值语义,并想知道在哪里添加间接寻址以使其可移植。因此,您可以使用pimpl习惯用法和一些条件编译。根据您希望构建工具的复杂性在哪里,以及如果您希望使所有低级代码尽可能自包含,请执行以下操作: 在高级标题
Thread.hpp
中,您定义:
class Thread
{
class Impl:
Impl *pimpl; // or better yet, some smart pointer
public:
Thread ();
~Thread();
// Other stuff;
};
然后,在线程源目录中,您可以按照以下方式定义文件:
Thread\u PlatformA.cpp
#ifdef PLATFORM_A
#include <Thread.hpp>
Thread::Thread()
{
// Platform A specific code goes here, initialize the pimpl;
}
Thread::~Thread()
{
// Platform A specific code goes here, release the pimpl;
}
#endif
#ifdef平台A
#包括
线程::线程()
{
//平台一个特定的代码在这里,初始化pimpl;
}
线程::~Thread()
{
//平台一个特定的代码放在这里,释放pimpl;
}
#恩迪夫
构建
Thread.o
变得很简单,只需将所有Thread.*.cpp
文件保存在Thread目录中,并让构建系统为编译器提供正确的-D
选项。我很好奇,这种情况下的设计是什么样的(只是坚持线程):
它不包含任何关于实现的内容,只包含接口
那么你有:
// platformA directory
class PlatformAThread { ... };
这将自动导致,当您创建“泛型”Thread
对象时,您也会自动获得一个平台相关类,该类会自动设置其内部,并且可能具有特定于平台的操作,当然,您的PlatformAThread
类可能派生自一个通用的Base
类,该类具有您可能需要的公共内容
您还需要设置生成系统以自动识别特定于平台的目录
另外,请注意,我倾向于创建类继承的层次结构,有些人建议不要这样做:还没有阅读您的整个问题。但是C++从C++ 11起就有了一个线程抽象层。我正在研究一个嵌入的目标,FreeRTOS支持线程的东西。另一个平台是基于计算机的仿真,用于更容易地开发高级代码。我认为C++11不支持这种情况。当然不是一个单独的
线程
类,而是线程
类的单独实现。我不遵循include路径,因为这些是源目录:)如果我写两个不同的c
// Your generic include level:
// thread.h
class Thread : public
#ifdef PLATFORM_A
PlatformAThread
#elif PLATFORM_B
PlatformBThread
// any more stuff you need in here
#endif
{
Thread();
virtual ~Thread();
void start();
void stop();
virtual void callback() = 0;
} ;
// platformA directory
class PlatformAThread { ... };