抽象工厂模式
理论
抽象工厂模式(Abstract Factory),提供一个创建一系列相关或相互依赖对象的接口,而无需指定它们具体的类。
抽象工厂模式的优点:
1. 最大的好处是易于交换产品系列,由于具体工厂类,在一个应用中只需要在初始化的时候出现一次,这就使得改变一个应用的具体工厂变得非常容易,它只需要改变具体工厂即可使用不同的产品配置。
2. 第二好处是,它让具体的创建实例过程于客户端分离,客户端是通过它们的抽象接口操纵实例,产品的具体类名也被具体工厂的实现分离,不会出现在客户代码中。
实例
实现数据库访问,要求包含“新增用户”和“得到用户”
用户有 ID 和 Name 两个属性
初步实现
#include <iostream> using namespace std; //用户类 class User { public: User(int id, string name){ ID = id; Name = name; } private: int ID; string Name; }; //Sqlserver数据库类 class SqlserverUser { public: void Insert(User* user) { cout << "在SQL Server中给User表增加一条记录" << endl; } void GetUser(int id){ cout << "在SQL Server中根据ID得到User表一条记录" << endl; } }; //Access数据库类 class AccessUser { public: void Insert(User* user) { cout << "在Access中给User表增加一条记录" << endl; } void GetUser(int id) { cout << "在Access中根据ID得到User表一条记录" << endl; } }; //客户端 int main() { User* user = new User(1, "小明"); SqlserverUser* su = new SqlserverUser(); su->Insert(user); //插入用户 su->GetUser(1); //得到ID为1的用户 delete user; system("pause"); return 0; }
工厂方法模式
UML类图
代码实现
#include <iostream> using namespace std; class User { public: User(int id, string name) { ID = id; Name = name; } private: int ID; string Name; }; //抽象数据库类 class AbstractUser { public: virtual void Insert(User* user) {}; virtual void GetUser(int id) {}; }; //具体数据库类 class SqlserverUser :public AbstractUser { public: void Insert(User* user) { cout << "在SQL Server中给User表增加一条记录" << endl; } void GetUser(int id) { cout << "在SQL Server中根据ID得到User表一条记录" << endl; } }; class AccessUser : public AbstractUser { public: void Insert(User* user) { cout << "在Access中给User表增加一条记录" << endl; } void GetUser(int id) { cout << "在Access中根据ID得到User表一条记录" << endl; } }; //抽象工厂类 class AbstractFactory { public: virtual AbstractUser* CreateUser() = 0; }; //具体工厂类 class SqlServerFactory : public AbstractFactory { public: AbstractUser* CreateUser() { return new SqlserverUser(); } }; class AccessFactory : public AbstractFactory { public: AbstractUser* CreateUser() { return new AccessUser(); } }; int main() { User* user = new User(1, "小明"); AbstractFactory* factory = new SqlServerFactory(); AbstractUser* iu = factory->CreateUser(); iu->Insert(user); iu->GetUser(1); delete factory; delete user; delete iu; system("pause"); return 0; }
抽象工厂模式
UML类图
代码实现
#include <iostream> using namespace std; class User { public: User(int id, string name) { ID = id; Name = name; } private: int ID; string Name; }; class Department { public: Department(string _department) { department = _department; } private: string department; }; //抽象部门类 class AbstractDepartment { public: virtual void Insert(Department* department) {}; virtual void GetDepartment(int id) {}; }; //具体部门类 class SqlserverDepartment :public AbstractDepartment { public: void Insert(Department* department) { cout << "在SQL Server中给Department表增加一条记录" << endl; } void GetDepartment(int id) { cout << "在SQL Server中根据ID得到Department表一条记录" << endl; } }; class AccessDepartment :public AbstractDepartment { public: void Insert(Department* department) { cout << "在Access中给Department表增加一条记录" << endl; } void GetDepartment(int id) { cout << "在Access中根据ID得到Department表一条记录" << endl; } }; //抽象数据库类 class AbstractUser { public: virtual void Insert(User* user) {}; virtual void GetUser(int id) {}; }; //具体数据库类 class SqlserverUser :public AbstractUser { public: void Insert(User* user) { cout << "在SQL Server中给User表增加一条记录" << endl; } void GetUser(int id) { cout << "在SQL Server中根据ID得到User表一条记录" << endl; } }; class AccessUser : public AbstractUser { public: void Insert(User* user) { cout << "在Access中给User表增加一条记录" << endl; } void GetUser(int id) { cout << "在Access中根据ID得到User表一条记录" << endl; } }; //抽象工厂类 class AbstractFactory { public: virtual AbstractUser* CreateUser()= 0; virtual AbstractDepartment* CreateDepartment() = 0; }; //具体工厂类 class SqlServerFactory : public AbstractFactory { public: AbstractUser* CreateUser() { return new SqlserverUser(); } AbstractDepartment* CreateDepartment() { return new SqlserverDepartment(); } }; class AccessFactory : public AbstractFactory { public: AbstractUser* CreateUser() { return new AccessUser(); } AbstractDepartment* CreateDepartment() { return new AccessDepartment(); } }; int main() { User* user = new User(1, "小明"); Department* department = new Department("研发部"); AbstractFactory* factory = new SqlServerFactory(); AbstractUser* iu = factory->CreateUser(); iu->Insert(user); iu->GetUser(1); delete user; delete iu; AbstractDepartment* id = factory->CreateDepartment(); id->Insert(department); id->GetDepartment(1); delete department; delete factory; delete id; system("pause"); return 0; }
只有一个 User 类和 User 操作类的时候,只需要工厂方法模式。当数据库中有很多的表,而 SOL Server 和 Access 又是两个不同的分类,所以解决这种涉及到多个产品系列的问题,就需要用一种专门的工厂模式叫抽象工厂模式。
抽象工厂模式的缺点:
如果有增加功能的需求,比如要增加项目表 Project,就需要增加三个类 AbstractProject、SqlserverProject、AccessProject,还需要更改对应的三个工厂类才可以完全实现。
而且当有很多客户端程序时,会有很多地方在使用 AbstractUser 或 AbstractDepartment, 这样的设计需要在每一个类的开始声明 AbstractFactory* factory = new SqlServerFactory(); 会导致在更改数据库时改动所有的声明。
简单工厂+抽象工厂
UML类图
代码实现
#include <iostream> using namespace std; class User { public: User(int id, string name) { ID = id; Name = name; } private: int ID; string Name; }; class Department { public: Department(string _department) { department = _department; } private: string department; }; //抽象部门类 class AbstractDepartment { public: virtual void Insert(Department* department) {}; virtual void GetDepartment(int id) {}; }; //具体部门类 class SqlserverDepartment :public AbstractDepartment { public: void Insert(Department* department) { cout << "在SQL Server中给Department表增加一条记录" << endl; } void GetDepartment(int id) { cout << "在SQL Server中根据ID得到Department表一条记录" << endl; } }; class AccessDepartment :public AbstractDepartment { public: void Insert(Department* department) { cout << "在Access中给Department表增加一条记录" << endl; } void GetDepartment(int id) { cout << "在Access中根据ID得到Department表一条记录" << endl; } }; //抽象数据库类 class AbstractUser { public: virtual void Insert(User* user) {}; virtual void GetUser(int id) {}; }; //具体数据库类 class SqlserverUser :public AbstractUser { public: void Insert(User* user) { cout << "在SQL Server中给User表增加一条记录" << endl; } void GetUser(int id) { cout << "在SQL Server中根据ID得到User表一条记录" << endl; } }; class AccessUser : public AbstractUser { public: void Insert(User* user) { cout << "在Access中给User表增加一条记录" << endl; } void GetUser(int id) { cout << "在Access中根据ID得到User表一条记录" << endl; } }; class DataSelect { public: AbstractUser* CreatUser() { AbstractUser* result = NULL; if (db == "Sqlserver") { result = new SqlserverUser(); } else if (db == "Access") { result = new AccessUser(); } return result; } AbstractDepartment* CreatDepartment() { AbstractDepartment* result = NULL; if (db == "Sqlserver") { result = new SqlserverDepartment(); } else if (db == "Access") { result = new AccessDepartment(); } return result; } private: string db = "Sqlserver"; //string db = "Access" }; int main() { User* user = new User(1, "小明"); Department* department = new Department("研发部"); DataSelect* data = new DataSelect(); AbstractUser* iu = data->CreatUser(); iu->Insert(user); iu->GetUser(1); delete user; delete iu; AbstractDepartment* id = data->CreatDepartment(); id->Insert(department); id->GetDepartment(1); delete department; delete data; delete id; system("pause"); return 0; }
另外, 在 C# 中,所有在用简单工厂的地方,都可以考虑用反射技术来去除 switch 和 if,解除分支判断带来的耦合。
后续:C++中也可继续改进。