抽象工厂模式

理论

 抽象工厂模式(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# 中,所有在用简单工厂的地方,都可以考虑用反射技术来去除 switchif,解除分支判断带来的耦合。

后续:C++中也可继续改进。

posted @ 2022-09-14 21:35  KYZH  阅读(76)  评论(0编辑  收藏  举报