大話設計模式:抽象工廠模式

塵虛緣_KY發表於2016-07-16
抽象方法模式:提供一個建立一系列相關或互相依賴物件的介面,而無需指定他們具體的類。
三種模式的對比:
  簡單工廠模式 工廠模式 抽象工廠模式
產品 可以有多個但是都屬於同一類,
同一等級。都繼承產品抽象類。
可以有多個但是都屬於同一類,同一等級。
都繼承產品抽象類。
可以有不同種類的產品,每類有多中
具體產品;
抽象產品 只能有一個 只能有一個; 多個抽象產品類;每個抽象產品類可
以派生多種具體產品;
抽象工廠類   只能有一個,可以派生出多個具體工廠類; 只有一個,可派生出多個具體工廠類;
具體工廠 製造不同的產品,直接例項化
產品物件;
一個具體工廠類只能建立一個具體的產品; 可以建立多個具體產品類的例項;








以書上的資料庫訪問為例:
抽象工廠中的角色有:
(1)抽象工廠:只能一個(IFactory)
(2)具體工廠: 包括具體工廠1:SqlServerFactory和具體工廠2:AccessFactory。
          具體工廠1用於生產具體產品A1:SqlserverUser和具體產品B1:SqlserverDepartment,
          具體工廠2用於生產具體產品A2:AccessUser和B2;AccessDepartment,
(3)抽象產品: 包括抽象產品A:IUser和抽象產品B:IDepartment;
(4)具體產品:包括抽象產品A所對應的具體產品A1和A2,以及抽象產品B所對應的具體產品B1和B2.
優點:
(1)抽象工廠模式是對工廠方法模式的改進,可以處理多類的產品,不侷限與某一類,因為有多個抽象產品類。例如此例如果在工廠方法模式下,產品只有User或者Department其中的一類,而抽象工廠模式下,產品包括User和Department兩類)
(2)易於交換產品系列,例如我們在選擇資料庫時,只需要初始化一次AccessFactory或者SqlServerFactory,就可以使用不同資料庫的配置,使之使用非常靈活。另外它使建立例項的過程與客戶端分離。很好的符合了開放-封閉原則和依賴倒轉原則。
缺點:如果要增加一個新的功能,需要改動的地方太多。
例如如果我們要增加一個新的專案表Project,那麼我的增加至少三個類:IProject,SqlserverProject、AccessProject,還需要更改抽象類IFactory、SqlserverFactory和AccessFactory才可以實現,這是非常多的。
其UML圖如下:

具體實現程式碼如下:
#include <iostream>  
using namespace std;  

//資料庫表項:User  
class User  
{  
private:  
	int id;  
	string name;  
public:  
	int getID()  
	{  
		return id;  
	}  
	string getName()  
	{  
		return name;  
	}  
	void setID(int ID)  
	{  
		this->id=ID;  
	}  
	void setName(string NAME)  
	{  
		this->name=NAME;  
	}  
};  


//資料庫表項:Department  
class Department  
{  
private:  
	int id;  
	string name;  
public:  
	int getID()  
	{  
		return id;  
	}  
	string getName()  
	{  
		return name;  
	}  
	void setID(int ID)  
	{  
		this->id=ID;  
	}  
	void setName(string NAME)  
	{  
		this->name=NAME;  
	}  
};  



//抽象產品A:IUser  
class IUser  
{  
public:  
	virtual void Insert(User user)=0;  
	virtual User* GetUser(int id)=0;  
};  
//具體產品A1:SqlserverUser  
class SqlserverUser:public IUser  
{  
public:  
	void Insert(User user)  
	{  
		cout<<"在SQL Server中給User表增加了一條記錄"<<endl;  
	}  
	User* GetUser(int id)  
	{  
		cout<<"在SQL Server中根據ID得到User表一條記錄"<<endl;  
		return NULL;  
	}  
};  
//具體產品A2:AccessUser  
class AccessUser:public IUser  
{  
public:  
	void Insert(User user)  
	{  
		cout<<"在Access中給User表增加了一條記錄"<<endl;  
	}  
	User* GetUser(int id)  
	{  
		cout<<"在Access中根據ID得到User表一條記錄"<<endl;  
		return NULL;  
	}  
};  


//抽象產品B:IDepartment  
class IDepartment  
{  
public:  
	virtual void Insert(Department department)=0;  
	virtual Department* GetDepartment(int id)=0;  
};  
//具體產品B1:SqlserverDepartment  
class SqlserverDepartment:public IDepartment  
{  
public:  
	void Insert(Department department)  
	{  
		cout<<"在Sql Server中給Department表新增了一條記錄"<<endl;  
	}  
	Department* GetDepartment(int id)  
	{  
		cout<<"在SQL Server中根據ID得到Department表的一條記錄"<<endl;  
		return NULL;  
	}  
};  
//具體產品B2:AccessDepartment  
class AccessDepartment:public IDepartment  
{  
public:  
	void Insert(Department department)  
	{  
		cout<<"在Access中給Department表新增了一條記錄"<<endl;  
	}  
	Department* GetDepartment(int id)  
	{  
		cout<<"在Access中根據ID得到Department表的一條記錄"<<endl;  
		return NULL;  
	}  
};  

//抽象工廠:IFactory  
class IFactory  
{  
public:  
	virtual IUser* CreateUser()=0;  
	virtual IDepartment* CreateDepartment()=0;  
};  
//具體工廠1:SqlServerFactory  
class SqlserverFactory:public IFactory  
{  
public:  
	IUser* CreateUser()  
	{  
		return new SqlserverUser;  
	}  

	IDepartment* CreateDepartment()  
	{  
		return new SqlserverDepartment;  
	}  
};  
//具體工廠2:AccessFactory  
class AccessFactory:public IFactory  
{  
public:  
	IUser* CreateUser()  
	{  
		return new AccessUser;  
	}  

	IDepartment* CreateDepartment()  
	{  
		return new AccessDepartment;  
	}  
};  
//客戶端  
int  main()  
{  
	User user;  
	Department department;  

	//ConcreteFactory1  
	IFactory* factory=NULL;  
	factory=new SqlserverFactory;  

	//ProductA1  
	IUser* iu=NULL;  
	iu=factory->CreateUser();  
	iu->Insert(user);  
	iu->GetUser(1);  

	//ProductB1  
	IDepartment* id=NULL;  
	id=factory->CreateDepartment();  
	id->Insert(department);  
	id->GetDepartment(1);  

	if(factory!=NULL)  
	{  
		delete factory;  
		factory=NULL;  
	}  
	if(iu!=NULL)  
	{  
		delete iu;  
		iu=NULL;  
	}  
	if(id!=NULL)  
	{  
		delete id;  
		id=NULL;  
	}  

	system("pause");  
	return 0;
}  
執行結果:

  小結:如果產品單一,要想達到以上的效果,合適用工廠模式;但是如果有多個品種分級時,通過抽象工廠模式產生需要的物件是一種非常好的解決方式。可以根據實際情況進行選擇。



相關文章