平时口头上说的“Adapter Pattern”是指,库代码与实际应用端的功能需求不一致,但确实存在一部分的库代码可以重用,于是把库代码适配成所需的功能接口,于是“生出”一个适配器类,给某一个/或多个库中的作了一次功能包装,顺便补上没有的功能,所以,往往有如下这样的code:
// windowInterface是库的接口类,window_win32/window_qt/window_gtk是库中的实现类的情况下
class MyWindowAdaptor: public windowInterface, protected window_win32
{
public:
//一些所需的接口函数...
void resize(int x, int y) { // eg.
// ...
window_win32::resize(x,y);
}
};
或是
class MyWindowAdaptor: public windowInterface{
public:
//一些所需的接口函数...
void resize(int x, int y) { // eg.
// ...
winImpl_.resize(x,y);
}
private:
window_win32 winImpl_;
};
而pixeltoastor里面使用了一丁点的宏,完成了类似的事情,并且由此得到了平台可移植性,把平台相关的实现代码约束在编译期,使得用户代码更为clear,大致的轮廓如下:
// window interface
struct WindowAdaptor {
virtual ~WindowAdaptor() {}
virtual void set(int ) =0;
virtual int get() =0;
virtual void update() =0;
virtual void resize(int , int ) =0;
};
// device interface
struct GraphicAdaptor {
virtual ~GraphicAdaptor() {}
virtual bool beginScene() =0;
virtual void endScene() =0;
virtual void clearScene() =0;
virtual void drawTriangle(Tri* pStart, unsigned count) =0;
};
// platform config macro
#ifdef WIN32
# define USE_OGL
# define USE_DX9
#elif LINUX
# define USE_OGL
#endif
// window implement
#ifdef WIN32
class Window_win32: public WindowAdaptor {
public:
virtual ~Window_win32() {}
virtual void set(int )
{ }
virtual int get()
{ return 0; }
virtual void update()
{ }
virtual void resize(int , int )
{ }
// ...
};
#define Window Window_win32
#endif
#ifdef LINUX
class Window_Linux: public WindowAdaptor {
// implement code...
};
#define Window Window_Linux
#endif
// device implement
#ifdef USE_DX9
class GraphicDevice_Dx9: public GraphicAdaptor {
// implement code...
};
#define GraphicDx9 GraphicDevice_Dx9
#endif
#ifdef USE_OGL
class GraphicDevice_OGL: public GraphicAdaptor {
// implement code...
};
#define GraphicOGL GraphicDevice_OGL
#endif
/* --------------------user code------------------------
// Display
class Display: public Window, public GraphicDx9 {
};
int main()
{
Display disp;
//...
return 0;
}
*/
以上只是表示了逻辑结构,同时其物理结构也想象的出了!
这里保证了类型安全,不失灵活性与健壮性,却引入了可以接受的隐含的名称冲突,像这样的idom可以应用到与具体平台或设备相关的programming任务上,如:音频处理模块、输入设备模块。
{ Message("新春愉快!", "^o^"); }