011 --- 第15章 抽象工厂模式
简述:
抽象工厂模式:提供一个创建一系列相关或相互依赖的对象的接口,而无需指定它们具体的类。
抽象工厂模式包括:抽象工厂类、具体工厂类、抽象产品类、具体产品类
抽象工厂类,它里面应该包含所有的产品创建的抽象方法。
具体工厂类:创建具有特定实现的产品对象。
抽象产品类:它们都有可能有几种不同的实现。
具体产品类:对抽象产品的具体分类的实现。
应用场景:所有在用简单工厂的地方,都可以考虑用反射技术来去除switch或if,接触分支判断带来的耦合
注:抽象工厂模式C#可以用反射的技术来实现,但是C++没有这种已经封装好的技术,所以我自己利用MFC的动态创建对象技术来模拟了反射技术实现的抽象工厂模式。
注:开发环境调整为VS2017,操作系统win11
例:调用不同的数据库
代码如下:
CDynamicCreateObject.h(动态创建对象头文件):
1 #pragma once 2 3 #ifndef _DYNAMICCREATEOBJECT_H_ 4 #define _DYNAMICCREATEOBJECT_H_ 5 6 #include <iostream> 7 using namespace std; 8 9 #define DECLARE_DYNAMICCREATEOBJECT() \ 10 static CRunTime RunTime; \ 11 static CDynamicCreateObject* CreateObject(); 12 13 #define IMPLEMENT_DYNAMICCREATEOBJECT(ThisClass) \ 14 CDynamicCreateObject* ThisClass::CreateObject() \ 15 { \ 16 return new ThisClass; \ 17 } \ 18 CRunTime ThisClass::RunTime = { #ThisClass, &ThisClass::CreateObject, NULL }; \ 19 CInitObjectList InitObjectList##ThisClass(&ThisClass::RunTime); 20 21 22 class CDynamicCreateObject 23 { 24 public: 25 static CDynamicCreateObject* MateStringThenCreateObject(string szClassName); 26 }; 27 28 class CRunTime 29 { 30 public: 31 string m_szClassName; 32 CDynamicCreateObject* (*pFunCreateObject)(); 33 CRunTime* pNext; 34 static CRunTime* pTop; 35 }; 36 37 class CInitObjectList 38 { 39 public: 40 CInitObjectList(CRunTime* pRunTime) 41 { 42 pRunTime->pNext = CRunTime::pTop; 43 CRunTime::pTop = pRunTime; 44 } 45 }; 46 47 #endif //_DYNAMICCREATEOBJECT_H_
CDynamicCreateObject.cpp(动态创建对象源文件):
1 #include "CDynamicCreateObject.h" 2 3 CRunTime* CRunTime::pTop = NULL; 4 5 CDynamicCreateObject* CDynamicCreateObject::MateStringThenCreateObject(string szClassName) 6 { 7 CRunTime* pRunTime = CRunTime::pTop; 8 while (pRunTime) 9 { 10 if (pRunTime->m_szClassName == szClassName) 11 { 12 if (pRunTime->pFunCreateObject == NULL) 13 return NULL; 14 else 15 return (*(pRunTime->pFunCreateObject))(); 16 } 17 pRunTime = pRunTime->pNext; 18 } 19 return NULL; 20 }
抽象工厂模式代码:
1 #include <iostream> 2 #include <string> 3 // 增加动态创建对象功能,这是由于C++没有C#中的反射技术,但可以自己模拟MFC中的动态创建对象技术实现 4 #include "CDynamicCreateObject.h" 5 using namespace std; 6 7 // 用户表类 8 class CUser 9 { 10 private: 11 int m_nID; 12 string m_szName; 13 14 public: 15 CUser() : m_nID(0), m_szName("") {}; 16 17 int GetID() { return m_nID; } 18 void SetID(int nID) { m_nID = nID; } 19 20 string GetName(){ return m_szName; } 21 void SetName(string szName){ m_szName = szName; } 22 }; 23 24 // 部门表类 25 class CDepartment{}; 26 27 // IUser(抽象产品类) 28 class CDatabaseUser : 29 public CDynamicCreateObject 30 { 31 public: 32 virtual void Insert(CUser* pUser) = 0; 33 virtual CUser* GetUser(int nID) = 0; 34 }; 35 36 // SQLServerUser(具体产品类) 37 class CSQLServerUser : public CDatabaseUser 38 { 39 // 抽象工厂模式动态创建 40 public: 41 DECLARE_DYNAMICCREATEOBJECT() 42 // 抽象工厂模式动态创建 43 public: 44 void Insert(CUser* pUser) 45 { 46 cout << "在SQL Server中给User表增加一条记录。" << endl; 47 } 48 49 CUser* GetUser(int nID) 50 { 51 cout << "在SQL Server中根据ID得到User表一条记录。" << endl; 52 return NULL; 53 } 54 }; 55 // 抽象工厂模式动态创建 56 IMPLEMENT_DYNAMICCREATEOBJECT(CSQLServerUser) 57 // 抽象工厂模式动态创建 58 59 // AccessUser(具体产品类) 60 class CAccessUser : public CDatabaseUser 61 { 62 // 抽象工厂模式动态创建 63 public: 64 DECLARE_DYNAMICCREATEOBJECT() 65 // 抽象工厂模式动态创建 66 public: 67 void Insert(CUser* pUser) 68 { 69 cout << "在Access中给User表增加一条记录。" << endl; 70 } 71 72 CUser* GetUser(int nID) 73 { 74 cout << "在Access中根据ID得到User表一条记录。" << endl; 75 return NULL; 76 } 77 }; 78 // 抽象工厂模式动态创建 79 IMPLEMENT_DYNAMICCREATEOBJECT(CAccessUser) 80 // 抽象工厂模式动态创建 81 82 // IDepartment(抽象产品类) 83 class CDatabaseDepartment : 84 public CDynamicCreateObject 85 { 86 public: 87 virtual void Insert(CDepartment* pDepartment) = 0; 88 virtual CDepartment* GetDepartment(int nID) = 0; 89 }; 90 91 // SQLServerDepartment(具体产品类) 92 class CSQLServerDepartment : public CDatabaseDepartment 93 { 94 // 抽象工厂模式动态创建 95 public: 96 DECLARE_DYNAMICCREATEOBJECT() 97 // 抽象工厂模式动态创建 98 public: 99 void Insert(CDepartment* pDepartment) 100 { 101 cout << "在SQL Server中给Department表增加一条记录。" << endl; 102 } 103 104 CDepartment* GetDepartment(int nID) 105 { 106 cout << "在SQL Server中根据ID得到Department表一条记录。" << endl; 107 return NULL; 108 } 109 }; 110 // 抽象工厂模式动态创建 111 IMPLEMENT_DYNAMICCREATEOBJECT(CSQLServerDepartment) 112 // 抽象工厂模式动态创建 113 114 // AccessDepartment(具体产品类) 115 class CAccessDepartment : public CDatabaseDepartment 116 { 117 // 抽象工厂模式动态创建 118 public: 119 DECLARE_DYNAMICCREATEOBJECT() 120 // 抽象工厂模式动态创建 121 public: 122 void Insert(CDepartment* pDepartment) 123 { 124 cout << "在Access中给Department表增加一条记录。" << endl; 125 } 126 127 CDepartment* GetDepartment(int nID) 128 { 129 cout << "在Access中根据ID得到Department表一条记录。" << endl; 130 return NULL; 131 } 132 }; 133 // 抽象工厂模式动态创建 134 IMPLEMENT_DYNAMICCREATEOBJECT(CAccessDepartment) 135 // 抽象工厂模式动态创建 136 137 //// 工厂方法模式举例-------------------- 138 //// IFactory(抽象工厂类) 139 //class CFactory 140 //{ 141 //public: 142 // virtual CDatabaseUser* CreateDatabaseUser() = 0; 143 // virtual CDatabaseDepartment* CreateDatabaseDepartment() = 0; 144 //}; 145 // 146 //// SQLServerFactory(具体工厂类) 147 //class CSQLServerFactory : public CFactory 148 //{ 149 //public: 150 // virtual CDatabaseUser* CreateDatabaseUser() 151 // { 152 // return new CSQLServerUser(); 153 // } 154 // 155 // virtual CDatabaseDepartment* CreateDatabaseDepartment() 156 // { 157 // return new CSQLServerDepartment(); 158 // } 159 //}; 160 // 161 //// AccessFactory(具体工厂类) 162 //class CAccessFactory : public CFactory 163 //{ 164 //public: 165 // virtual CDatabaseUser* CreateDatabaseUser() 166 // { 167 // return new CAccessUser(); 168 // } 169 // 170 // virtual CDatabaseDepartment* CreateDatabaseDepartment() 171 // { 172 // return new CAccessDepartment(); 173 // } 174 //}; 175 //// 工厂方法模式举例-------------------- 176 // 177 //// 简单工厂模式举例-------------------- 178 //// DataAccess(简单工厂模式工厂类) 179 //class CDataAccess 180 //{ 181 //private: 182 // enum DATABASE{SQLServer, Access} ; 183 // static const int m_nDB; 184 // 185 //public: 186 // static CDatabaseUser* CreateDatabaseUser() 187 // { 188 // CDatabaseUser* pDatabaseUser = NULL; 189 // switch (m_nDB) 190 // { 191 // case SQLServer: 192 // pDatabaseUser = new CSQLServerUser(); 193 // break; 194 // 195 // case Access: 196 // pDatabaseUser = new CAccessUser(); 197 // break; 198 // } 199 // 200 // return pDatabaseUser; 201 // } 202 // 203 // static CDatabaseDepartment* CreateDatabaseDepartment() 204 // { 205 // CDatabaseDepartment* pDatabaseDepartment = NULL; 206 // switch (m_nDB) 207 // { 208 // case SQLServer: 209 // pDatabaseDepartment = new CSQLServerDepartment(); 210 // break; 211 // 212 // case Access: 213 // pDatabaseDepartment = new CAccessDepartment(); 214 // break; 215 // } 216 // 217 // return pDatabaseDepartment; 218 // } 219 //}; 220 // 221 //const int CDataAccess::m_nDB = SQLServer; 222 //// 简单工厂模式举例-------------------- 223 224 // 抽象工厂模式举例-------------------- 225 // DataAccess(抽象工厂模式工厂类) 226 class CDataAccessAbstract 227 { 228 private: 229 static string m_szUserName; 230 static string m_szDepartmentName; 231 public: 232 static CDatabaseUser* CreateDatabaseUser() 233 { 234 return (CDatabaseUser*)CDynamicCreateObject::MateStringThenCreateObject(m_szUserName); 235 } 236 237 static CDatabaseDepartment* CreateDatabaseDepartment() 238 { 239 return (CDatabaseDepartment*)CDynamicCreateObject::MateStringThenCreateObject(m_szDepartmentName); 240 } 241 }; 242 // 字符串从配置文件中读取功能略(并不难,不过不需要解析xml,直接读取整行,解析键值对就可以,键值对类似于:UserName = CAccessUser) 243 string CDataAccessAbstract::m_szUserName = "CAccessUser"; 244 string CDataAccessAbstract::m_szDepartmentName = "CSQLServerDepartment"; 245 // 抽象工厂模式举例-------------------- 246 247 248 int main() 249 { 250 CUser User; 251 CDepartment Department; 252 253 CDatabaseUser* pDatabaseUser = CDataAccessAbstract::CreateDatabaseUser(); 254 pDatabaseUser->Insert(&User); 255 pDatabaseUser->GetUser(1); 256 delete pDatabaseUser; 257 258 CDatabaseDepartment* pDatabaseDepartment = CDataAccessAbstract::CreateDatabaseDepartment(); 259 pDatabaseDepartment->Insert(&Department); 260 pDatabaseDepartment->GetDepartment(1); 261 delete pDatabaseDepartment; 262 263 system("pause"); 264 return 0; 265 }
输出结果: