如果应用程序要适应不同平台的话,要封装那些对平台的依赖关系。如果不事先考虑好封装,程序中会出现很多#ifdef语句。
Abstract Factory模式,是用来代替new来创建那些相互之间有依赖关系的对象的。该模式把所有平台共同拥有的组件都找出来,然后一个个定义成平台无关的类,最后定义一个Factory,负责生成所有这些组件。客户在使用时,只需要使用该平台的Factory,就可以生成该平台独有的组件对象。
下面这个程序没有封装好平台相关性,所以看着很乱。
class Widget { public: virtual void draw() = 0; }; class MotifBtn : public Widget { public: void draw() { cout << "MotifBtn" << endl; } }; class WindowsBtn : public Widget { public: void draw() { cout << "WindowsBtn" << endl; } }; void doThisWindow() { // create window, attach btn #ifdef MOTIF Widget* w = new MotifBtn; #else // WINDOWS Widget* w = new WindowsBtn; #endif w->draw(); } void doThatWindow() { // create window, attach btn #ifdef MOTIF Widget* w = new MotifBtn; #else // WINDOWS Widget* w = new WindowsBtn; #endif w->draw(); } void main( void ) { // create window, attach btn #ifdef MOTIF Widget* w = new MotifBtn; #else // WINDOWS Widget* w = new WindowsBtn; #endif w->draw(); doThisWindow(); doThatWindow(); }
重构以后,成了下面这个样子:
// 这个Widget是平台无关的 class Widget { public: virtual void draw() = 0; }; class MotifBtn : public Widget { public: void draw() { cout << "MotifBtn" << endl; } }; class WindowsBtn : public Widget { public: void draw() { cout << "WindowsBtn" << endl; } }; // 这个Factory是平台无关的 class WidgetFactory { public: virtual Widget* makeBtn() = 0; static WidgetFactory* getInstance(); protected: WidgetFactory() {}; virtual ~WidgetFactory() {}; private: static WidgetFactory* s_widgetFactory; }; WidgetFactory* WidgetFactory::s_widgetFactory = NULL; class MotifFactory: public WidgetFactory { public: Widget* makeBtn() { return new MotifBtn; } }; class WindowsFactory: public WidgetFactory { public: Widget* makeBtn() { return new WindowsBtn; } }; // 基于Factory的特性,一般搞成Singleton WidgetFactory* WidgetFactory::getInstance() { if (s_widgetFactory == NULL) #ifdef MOTIF s_widgetFactory = new MotifFactory; #else // WINDOWS s_widgetFactory = new WindowsFactory; #endif return s_widgetFactory; } void doThisWindow() { Widget* widget = WidgetFactory::getInstance()->makeBtn(); widget->draw(); } void doThatWindow() { // create window, attach btn Widget* w = WidgetFactory::getInstance()->makeBtn(); w->draw(); } // 程序没有回收make出来的资源,故意为之 void main() { Widget* w = WidgetFactory::getInstance()->makeBtn(); w->draw(); doThisWindow(); doThatWindow(); }