### 对象工厂 Object Factory
又名简单工厂模式,貌似不属于设计模式范畴。它的作用是把对象的创建工作集中起来,并使创建工作与其它部分解耦。比如下面这个函数也可当作简单工厂:
1. CWinBase* Create(string s) 2. { 3. if(s =="Edit") 4. returnnewCEdit; 5. elseif(s =="Button") 6. returnnewCButton; 7. ... 8. }
Loki库的Factory类提供了对简单工厂模式的支持。
#### 头文件
1. #include
#### 类型
1. template< 2. classAbstractProduct, 3. typenameIdentifierType, 4. typenameCreatorParmTList = NullType, 5. template<typename,class>classFactoryErrorPolicy = DefaultFactoryError> 6. classLoki::Factory;
#### 成员方法
bool Register(const IdentifierType& id, ProductCreator creator); |
以id作为识别码注册生成器。函数、对象方法或仿函数都可以作为生成器。 |
bool Unregister(const IdentifierType& id); |
取消注册 |
std::vector RegisteredIds(); |
取得已注册的所有识别码 |
AbstractProduct* CreateObject(const IdentifierType& id); AbstractProduct* CreateObject(const IdentifierType& id, Parm1 p1); AbstractProduct* CreateObject(const IdentifierType& id, Parm1 p1, Parm2 p2); ... |
按识别码id生成对象(调用对应的生成器) |
#### 示例代码
1. #include 2. #include 3. #include 4. #include 5. 6. 7. structIWidget{ 8. virtualvoidprintName() = 0; 9. virtual~IWidget(){;} 10. }; 11. 12. typedefLoki::Factory widget_factory_t; 13. 14. structCButton : IWidget{ 15. voidprintName() 16. { 17. std::cout <<"CButton"<< std::endl; 18. } 19. }; 20. 21. structCEdit : IWidget{ 22. voidprintName() 23. { 24. std::cout <<"CEdit"<< std::endl; 25. } 26. }; 27. 28. structCListBox : IWidget{ 29. voidprintName() 30. { 31. std::cout <<"CListBox"<< std::endl; 32. } 33. }; 34. 35. int_tmain(intargc, _TCHAR* argv[]) 36. { 37. 38. widget_factory_t wf; 39. 40. wf.Register("Edit", Loki::CreateUsingNew::Create ); 41. wf.Register("Button", Loki::CreateUsingNew::Create ); 42. wf.Register("ListBox", Loki::CreateUsingNew::Create ); 43. 44. { 45. IWidget* pWid = wf.CreateObject("Edit"); 46. pWid->printName(); 47. deletepWid; 48. } 49. { 50. IWidget* pWid = wf.CreateObject("ListBox"); 51. pWid->printName(); 52. deletepWid; 53. } 54. return0; 55. }
很多时候,工厂往往只需要一个实例,我们可以使用前面说过的SingletonHolder把widget_factory_t弄成Singleton模式。
上面生成CButton之类的窗体时使用的是默认构造,所以我偷懒没写各个类的生成器,直接用了Loki::CreateUsingNew。
如果你的类有构造参数的话,那么就得在Loki::Factory模板参数中指出参数类型,并且自定义生成器,就象这样:
1. #include 2. #include 3. #include 4. 5. 6. structIWidget{ 7. virtualvoidprintName() = 0; 8. virtual~IWidget(){;} 9. }; 10. 11. typedefLoki::Factory< 12. IWidget, 13. std::string, 14. Loki::Seq<int,char> 15. > widget_factory_t; 16. 17. typedefLoki::SingletonHolder 18. Loki::LongevityLifetime::DieAsSmallObjectChild> Singleton_Fac; 19. 20. structCButton : IWidget{ 21. voidprintName() 22. { 23. std::cout <<"CButton:"<< m_txt << std::endl; 24. } 25. CButton(std::string txt,int,char) 26. :m_txt(txt){} 27. std::string m_txt; 28. }; 29. 30. structCEdit : IWidget{ 31. voidprintName() 32. { 33. std::cout <<"CEdit:"<< m_txt << std::endl; 34. } 35. CEdit(std::string txt,int,char) 36. :m_txt(txt){} 37. std::string m_txt; 38. }; 39. 40. structCListBox : IWidget{ 41. voidprintName() 42. { 43. std::cout <<"CListBox:"<< m_txt << std::endl; 44. } 45. CListBox(std::string txt,int,char) 46. :m_txt(txt){} 47. std::string m_txt; 48. }; 49. 50. template<classT>structCreateT 51. { 52. T * operator()(std::string txt,intp1,charp2)const 53. { 54. returnnewT(txt, p1, p2); 55. } 56. }; 57. 58. int_tmain(intargc, _TCHAR* argv[]) 59. { 60. 61. widget_factory_t& wf = Singleton_Fac::Instance(); 62. 63. 64. wf.Register("Edit", CreateT() ); 65. wf.Register("Button", CreateT() ); 66. wf.Register("ListBox", CreateT() ); 67. 68. 69. { 70. IWidget* pWid = wf.CreateObject("Edit","Hello", 0,' '); 71. pWid->printName(); 72. deletepWid; 73. } 74. { 75. IWidget* pWid = wf.CreateObject("ListBox","World", 0,' '); 76. pWid->printName(); 77. deletepWid; 78. } 79. 80. return0; 81. }
Loki::Seq是一个类似于TypeList的东东,可以存放一系列的类型。另外用SingletonHolder包装Factory时,一定要用Loki::LongevityLifetime::DieAsSmallObjectChild作为SingletonHolder的lifttime策略(Loki使用说明上说的,由于Factory使用了Loki内部的内存管理器SmallObject)。 |