抽象工厂模式
理论
抽象工厂模式(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++中也可继续改进。

浙公网安备 33010602011771号