抽象工厂
当每个抽象产品都有多于一个的具体子类的时候,工厂角色怎么知道实例化哪一个子类呢?比如每个抽象产品角色都有两个具体产品。抽象工厂模式提供两个具体工厂角色,分别对应于这两个具体产品角色,每一个具体工厂角色只负责某一个产品角色的实例化。每一个具体工厂类只负责创建抽象产品的某一个具体子类的实例。
单件模式
Singleton就是确保一个类只有唯一的一个实例。Singleton主要用于对象的创建,这意味着,如果某个类采用了Singleton模式,则在这个类被创建后,它将有且仅有一个实例可供访问。很多时候我们都会需要Singleton模式,最常见的比如我们希望整个应用程序中只有一个连接数据库的Connection实例;又比如要求一个应用程序中只存在某个用户数据结构的唯一实例。我们都可以通过应用Singleton模式达到目的。
实例
该公司数据库拥有三张表,分别是用户表、部门表和项目表。每张表的操作都支持查询和添加功能。数据库支持MySQL和SQL Server两种。结合抽象工厂模式和单件模式给出该系统的模拟代码。
在抽象工厂模式中,一个应用里一般每个产品只需要一个具体工厂的实例,因此,工厂通常最好用单件模式实现。实验要求结合抽象工厂模式和单件模式,模拟公司数据库创建过程。
UML图
C++代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 |
#include<iostream> using namespace std; class User{ int id; }; class Department{ int id; }; class Project{ int id; }; class IUser{ public: virtual void Insert(User* user) = 0; virtual User* GetUser(int id) = 0; }; class IDepartment{ public: virtual void Insert(Department* department) = 0; virtual Department* GetDepartment(int id) = 0; }; class IProject{ public: virtual void Insert(Project* project) = 0; virtual Project* GetProject(int id) = 0; }; class IFactory{ public: virtual ~IFactory(){cout<<"抽象工厂实例删除!"<<endl;} virtual IUser* CreateUser()=0; virtual IDepartment* CreateDepartment()=0; virtual IProject* CreateProject()=0; }; class SqlserverUser: public IUser{ public: void Insert(User* user){ cout<<"增加一个用户"<<endl; } User* GetUser(int id){ cout<<"得到一个用户"<<endl; return NULL; } }; class SqlserverDepartment: public IDepartment{ public: void Insert(Department* department){ cout<<"增加一个部门"<<endl; } Department* GetDepartment(int id){ cout<<"得到一个部门"<<endl; return NULL; } }; class SqlserverProject: public IProject{ public: void Insert(Project* project){ cout<<"增加一个项目"<<endl; } Project* GetProject(int id){ cout<<"得到一个项目"<<endl; return NULL; } }; class MysqlUser: public IUser{ public: void Insert(User* user){ cout<<"增加一个用户"<<endl; } User* GetUser(int id){ cout<<"得到一个用户"<<endl; return NULL; } }; class MysqlDepartment: public IDepartment{ public: void Insert(Department* department){ cout<<"增加一个部门"<<endl; } Department* GetDepartment(int id){ cout<<"得到一个部门"<<endl; return NULL; } }; class MysqlProject: public IProject{ public: void Insert(Project* project){ cout<<"增加一个项目"<<endl; } Project* GetProject(int id){ cout<<"得到一个项目"<<endl; return NULL; } }; class SqlserverFactory: public IFactory{ public: ~SqlserverFactory(){cout<<"SQL Server抽象工厂实例删除!"<<endl;} IUser* CreateUser(){ return new SqlserverUser(); } IDepartment* CreateDepartment(){ return new SqlserverDepartment(); } IProject* CreateProject(){ return new SqlserverProject(); } static IFactory *GetInstance(){ if (factory == NULL ){ return new SqlserverFactory(); cout<<"抽象工厂实例生成!"<<endl; }else cout<<"Error, 抽象工厂实例已有!"<<endl; return factory; } private: SqlserverFactory(){} static SqlserverFactory* factory; }; SqlserverFactory* SqlserverFactory::factory = NULL; class MysqlFactory: public IFactory{ public: ~MysqlFactory(){cout<<"SQL Server抽象工厂实例删除!"<<endl;} IUser* CreateUser(){ return new MysqlUser(); } IDepartment* CreateDepartment(){ return new MysqlDepartment(); } IProject* CreateProject(){ return new MysqlProject(); } static IFactory *GetInstance(){ if (factory == NULL ){ cout<<"抽象工厂实例生成!"<<endl; factory = new MysqlFactory(); }else cout<<"Error, 抽象工厂实例已有!"<<endl; return factory; } private: MysqlFactory(){} static MysqlFactory* factory; }; MysqlFactory* MysqlFactory::factory = NULL; int main(){ User* user = new User(); Department* dept = new Department(); Project* pro = new Project(); cout<<endl<<"MySQL"<<endl; IFactory *factory1 = MysqlFactory::GetInstance(); IFactory *factory2 = MysqlFactory::GetInstance(); //生成第二个失败 IUser* iu = factory1->CreateUser(); iu->Insert(user); iu->GetUser(1); IDepartment* idept = factory1->CreateDepartment(); idept->Insert(dept); idept->GetDepartment(1); IProject* ipro = factory1->CreateProject(); ipro->Insert(pro); ipro->GetProject(1); cout<<endl<<"SQL Server"<<endl; IFactory *factory12 = MysqlFactory::GetInstance(); IFactory *factory22 = MysqlFactory::GetInstance(); //生成第二个失败 IUser* iu2 = factory12->CreateUser(); iu->Insert(user); iu->GetUser(1); IDepartment* idept2 = factory12->CreateDepartment(); idept->Insert(dept); idept->GetDepartment(1); IProject* ipro2 = factory12->CreateProject(); ipro->Insert(pro); ipro->GetProject(1); return 0; } |
效果
注意第二行是再次生成一个MySQL的工厂,但是由于只能有一个,因此不能再次创建。
总结
- 注意使用单件模式写MySQL和SQL Server的具体工厂时,只能对自身单件,即生成一个MySQL工厂时,不能再次生成第二个MySQL工厂,但是可以生成SQL Server工厂。
- 当使用单件模式时,具体工厂的构造函数需要放在private中,这样客户端不能随意创建多个工厂。在public中需要增加getInstance函数用来判断是否生成了工厂,如果存在,则不能创建第二个,注意这是static类型。
- 具体工厂的指针需要在类外部全局部分进行初始化为NULL。