一、了解抽象工廠設計模式
書上說:提供一個創建一系列相關或相互依賴對象的接口,而無需制定他們具體的類。
二、看類圖
解說員:圖上分兩部分來看,一部分是左邊的IFactory家族,另一部分是右邊的IProduct 家族。
1、先看IProduct家族。
第一層:客戶需求。可以看出我們需要哪些產品,由客戶端決定,我們需要提前設計好第二層的產品。
第二層:ProductA和ProductB,這一系列的產品,具體要根據實際情況來確定。
第二層要說明的是:這個具體的產品的屬性是不變的,而我們要對這個產品進行的各種操作是變化的,為了符合開放——封閉,和封裝原則,在修改方法的時候不必影響到屬性,我們把這個產品類分成了兩部分,一部分是具體的名詞類,不包含任何方法,只有該類的屬性;另一部分是抽象接口:定義對該類的操作方法。這樣我們就可以單獨的對一個類的屬性或者是方法進行分別操作,而互不影響,做到面向對象的封裝。他們之間是依賴關系,接口依賴具體類。這個內部關系,在上圖中沒有變現出來。
也就是說,第三層實現的是第二層的接口方法,訪問和操作的是第二層的具體類。
第三層:A1,A2,則是具體的實現類了。他們是ProductA 的具體實現過程。可能實現有多種,SO,具體的實現類也要多個,當然也需要一個統一的接口來統一管理。這裡的接口就設在了第二層,有力第二層的接口,我們就可以在三層進行擴展,這也是一個封裝。
體現的原則
開放——封閉原則:對擴展開放,對修改封閉。
在這個三層圖上,有兩個接口,也就是有兩個地方可能發生變化,一個是數據庫的選擇,一個是訪問數據庫表的選擇。
依賴倒轉原則:抽象工廠的設計是由上自下逐步抽象的,且是針對接口編程,在最後一層才開始考慮具體的實現,提高了代碼的復用,分別體現了:高層模塊不依賴低層模塊;抽象不依賴細節。
單一原則:第三層的每個類都是對單一功能的實現,對一個數據庫表進行訪問。
舉例說明:用戶需要訪問數據庫,那第二層就是數據庫表,這些是哪個數據庫都具備的;從第一層到二層擴展為了將來對更多或者其他數據庫表的訪問;現在我們要訪問用戶表,或許以後,我們還需要訪問公司部門表,或者公司財務表;第三層應該考慮數據庫的具體訪問,操作實現,可擴展的子類有SQL server,Access 或者oracle。這些都是不同的實現過稱,但同屬於實現這一級別。可能現在用的是access,將來用SQL server,或者是Oracle,所以我們在要第二層為什麼准備了接口,以備第三層的多種實現。
2、看IFactory家族。
此處工廠不是具體的制造產品的工廠,只是一個中介所。為什麼這麼說?
第一層:定義了一個創建一系列相關或相互依賴對象的接口。
例如我們需要訪問的多個數據庫表都在其中定義。這也是區別於工廠模式的一點。工廠模式針對的是一類,而抽象工廠針對的是一系列產品。
第二層:具體實現訪問方法,他們根據客戶端實例化的對象,幫助用戶找到Iproduct 家族中第三層的地址,達到實現的目的。
練手:對SQL server和ACCESS兩種數據庫中的用戶表和部門表進行訪問。
[csharp]
//定義用戶表類——定義了用戶表的屬性
class User
{
private int id;
public int ID
{
get { return id; }
set { id = value; }
}
private string name;
public string Name
{
get { return name; }
set { name = value; }
}
}
//定義數據庫用戶表接口——定義了對用戶表的進行的操作
interface IUser
{
void Insert(User user);
User GetUser(int id);
}
//定義SQL數據庫表
class SqlserverUser:IUser
{
public void Insert(User user)
{
Console.WriteLine("在SQL 中增加一條用戶記錄");
}
public User GetUser(int id)
{
Console.WriteLine("在SQL 中根據ID得到一條用戶記錄");
return null;
}
}
//定義Access數據庫表
class AccessUser : IUser
{
public void Insert(User user)
{
Console.WriteLine("在Access 中增加一條用戶記錄");
}
public User GetUser(int id)
{
Console.WriteLine("在Access 中根據ID得到一條用戶記錄");
return null;
}
}
//定義數據庫部門表——屬性
class Department
{
private int id;
public int ID
{
get { return id; }
set { id = value; }
}
private string dname;
public string DName
{
get { return dname; }
set { dname = value; }
}
}
//定義操作部門的接口——操作
interface IDepartmnet
{
void Insert(Department department);
Department GetDepartment(int id);
}
//定義用於訪問部門的SQL 實現
class SQLdepartment:IDepartmnet
{
public void Insert(Department department)
{
Console.WriteLine("在SQL 中插入一條記錄!");
}
public Department GetDepartment(int id)
{
Console.WriteLine("根據ID 號取出部門!");
return null;
}
}
//定義用於訪問部門的Access 實現
class Accessdepartment : IDepartmnet
{
public void Insert(Department department)
{
Console.WriteLine("在SQL 中插入一條記錄!");
}
public Department GetDepartment(int id)
{
Console.WriteLine("根據ID 號取出部門!");
return null;
}
}
//定義訪問數據庫表的工廠接口
interface IFactory
{
IUser CreateUser();
IDepartmnet CreatDepartment();
}
//實例化SQL 工廠接口
class SqlFactory : IFactory
{
public IUser CreateUser()
{
return new SqlserverUser();
}
public IDepartmnet CreatDepartment()
{
return new SQLdepartment();
}
}
//實例化Access工廠接口
class AccessFactory : IFactory
{
public IUser CreateUser()
{
return new AccessUser();
}
public IDepartmnet CreatDepartment()
{
return new Accessdepartment();
}
}
static void Main(string[] args)
{
User user = new User();
Department department = new Department();
IFactory factory = new SqlFactory();
IUser iu = factory.CreateUser();
iu.Insert(user);
iu.GetUser(2);//任意的int類型的都可以
IFactory factory1 = new AccessFactory();
IUser au = factory1.CreateUser();
au.Insert(user);
au.GetUser(2);//任意的int類型的都可以
IFactory factoryd = new SqlFactory();
IDepartmnet id=factoryd .CreatDepartment ();
id.Insert (department );
id.GetDepartment (1);
IFactory factorya = new AccessFactory();
IDepartmnet ad=factoryd .CreatDepartment ();
ad.Insert (department );
ad.GetDepartment (1);
www.2cto.com
//IUser au = new AccessUser();
//au.Insert(user);
//au.GetUser(2);//任意的int類型的都可以
Console.Read();
}