這裡首先以一個生活中抽象工廠的例子來實現一個抽象工廠,然後再給出抽象工廠的定義和UML圖來幫助大家更好地掌握抽象工廠模式,同時大家在理解的時候,可以對照抽象工廠生活中例子的實現和它的定義來加深抽象工廠的UML圖理解。抽象工廠模式比其它工廠模式更加抽象,抽象工廠模式適用與多個抽象類的情況下,通過工廠返回多個抽象類中你需要得到的具體子類實例。
抽象工廠模式比其它工廠模式更加抽象,抽象工廠模式適用與多個抽象類的情況下,通過工廠返回多個抽象類中你需要得到的具體子類實例。
舉例闡述抽象工廠模式:
假如中國對邪惡國家開戰。
中國裝備:炸彈類,坦克類,來消滅邪惡國家。
炸彈類:導彈,核彈;
坦克類:越野車,主站坦克;
戰略:
前期中國兵工廠生產:導彈,越野車,打擊邪惡國家。
後期中國兵工廠生產:核彈,主站坦克,毀滅邪惡國家。
類圖:
裝備類代碼:
? 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138#region 炸彈系列
abstract
class
Bomb
{
abstract
public
void
baozha();
}
/// <summary>
/// 導彈
/// </summary>
class
daodanBomb :Bomb
{
public
override
void
baozha()
{
Console.WriteLine(
"我是一顆中國造導彈,來轟炸不老實的小邪惡國家!"
);
}
}
/// <summary>
/// 核彈
/// </summary>
class
hedanBomb : Bomb
{
public
override
void
baozha()
{
Console.WriteLine(
"我是一顆中國造核彈,來轟炸不老實的小邪惡國家!"
);
}
}
#endregion
#region 坦克系列
abstract
class
Tank
{
abstract
public
void
go();
}
/// <summary>
/// 越野車
/// </summary>
class
yueyeTank : Tank
{
public
override
void
go()
{
Console.WriteLine(
"我是一顆中國造越野車,來踏平不老實的小邪惡國家!"
);
}
}
/// <summary>
/// 主站坦克
/// </summary>
class
zhuzhanTank : Tank
{
public
override
void
go()
{
Console.WriteLine(
"我是一顆中國造主站坦克,來踏平不老實的小邪惡國家!"
);
}
}
#endregion工廠類代碼
#region 中國兵工廠
abstract
class
chinaFactory
{
//裝甲車制造車間
public
abstract
Tank CreateTank();
//炸彈知道車間
public
abstract
Bomb CreateBomb();
}
//兵工廠前期制造
class
qianqiFactory : chinaFactory
{
public
override
Bomb CreateBomb()
{
//導彈
return
new
daodanBomb();
}
public
override
Tank CreateTank()
{
//越野車
return
new
yueyeTank();
}
}
//兵工廠後期制造
class
houqiFactory : chinaFactory
{
public
override
Bomb CreateBomb()
{
//核彈
return
new
hedanBomb();
}
public
override
Tank CreateTank()
{
//主站坦克
return
new
zhuzhanTank();
}
}
#endregion客戶端代碼:(打仗)
// 備戰
class
Make
{
//裝備
private
Bomb bomb;
private
Tank tank;
//制造加工
public
Make(chinaFactory factory)
{
bomb = factory.CreateBomb();
tank = factory.CreateTank();
}
//開始打仗
public
void
warStar()
{
//炸彈類爆炸
bomb.baozha();
//戰車類前進
tank.go();
}
}
public
class
start
{
public
static
void
Main()
{
//大戰前期
chinaFactory qianqiMake =
new
qianqiFactory();
Make qianqi =
new
Make(qianqiMake);
qianqi.warStar();
//點任意鍵,進行後期攻勢!!
Console.ReadKey();
//大戰後期
chinaFactory houqiMake =
new
houqiFactory();
Make houqi =
new
Make(houqiMake);
houqi.warStar();
Console.WriteLine(
"釣魚島是中國的,神聖不可侵犯!小邪惡國家,滾開!!"
);
Console.ReadLine();
}
}
抽象工廠模式的定義和類圖
抽象工廠允許客戶使用抽象的接口來創建一組相關產品,而不需要知道或關心實際生產出的具體產品是什麼。這樣客戶就可以從具體產品中被解耦。下面通過抽象工模式的類圖來了解各個類中之間的關系:
抽象工廠的分析
抽象工廠模式將具體產品的創建延遲到具體工廠的子類中,這樣將對象的創建封裝起來,可以減少客戶端與具體產品類之間的依賴,從而使系統耦合度低,這樣更有利於後期的維護和擴展,這真是抽象工廠模式的優點所在,然後抽象模式同時也存在不足的地方。下面就具體看下抽象工廠的缺點(缺點其實在前面的介紹中以已經涉及了):
抽象工廠模式很難支持新種類產品的變化。這是因為抽象工廠接口中已經確定了可以被創建的產品集合,如果需要添加新產品,此時就必須去修改抽象工廠的接口,這樣就涉及到抽象工廠類的以及所有子類的改變,這樣也就違背了“開發——封閉”原則。
知道了抽象工廠的優缺點之後,也就能很好地把握什麼情況下考慮使用抽象工廠模式了,下面就具體看看使用抽象工廠模式的系統應該符合那幾個前提:
一個系統不要求依賴產品類實例如何被創建、組合和表達的表達,這點也是所有工廠模式應用的前提。
這個系統有多個系列產品,而系統中只消費其中某一系列產品
系統要求提供一個產品類的庫,所有產品以同樣的接口出現,客戶端不需要依賴具體實現。
.Net中抽象工廠模式實現
抽象工廠模式在實際中的應用也是相當頻繁的,然而在我們.Net類庫中也存在應用抽象工廠模式的類,這個類就是System.Data.Common.DbProviderFactory,這個類位於System.Data.dll程序集中,該類扮演抽象工廠模式中抽象工廠的角色,我們可以用reflector反編譯工具查看該類的實現:
/// 扮演抽象工廠的角色
/// 創建連接數據庫時所需要的對象集合,
/// 這個對象集合包括有 DbConnection對象(這個是抽象產品類,如絕味例子中的YaBo類)、DbCommand類、DbDataAdapter類,針對不同的具體工廠都需要實現該抽象類中方法,
public
abstract
class
DbProviderFactory
{
// 提供了創建具體產品的接口方法
protected
DbProviderFactory();
public
virtual
DbCommand CreateCommand();
public
virtual
DbCommandBuilder CreateCommandBuilder();
public
virtual
DbConnection CreateConnection();
public
virtual
DbConnectionStringBuilder CreateConnectionStringBuilder();
public
virtual
DbDataAdapter CreateDataAdapter();
public
virtual
DbDataSourceEnumerator CreateDataSourceEnumerator();
public
virtual
DbParameter CreateParameter();
public
virtual
CodeAccessPermission CreatePermission(PermissionState state);
}
DbProviderFactory類是一個抽象工廠類,該類提供了創建數據庫連接時所需要的對象集合的接口,實際創建的工作在其子類工廠中進行,微軟使用的是SQL Server數據庫,因此提供了連接SQL Server數據的具體工廠實現,具體代碼可以用反編譯工具查看,具體代碼如下:
/// 扮演著具體工廠的角色,用來創建連接SQL Server數據所需要的對象
public
sealed
class
SqlClIEntFactory : DbProviderFactory, IServiceProvider
{
// FIElds
public
static
readonly
SqlClIEntFactory Instance =
new
SqlClIEntFactory();
// 構造函數
private
SqlClIEntFactory()
{
}
// 重寫抽象工廠中的方法
public
override
DbCommand CreateCommand()
{
// 創建具體產品
return
new
SqlCommand();
}
public
override
DbCommandBuilder CreateCommandBuilder()
{
return
new
SqlCommandBuilder();
}
public
override
DbConnection CreateConnection()
{
return
new
SqlConnection();
}
public
override
DbConnectionStringBuilder CreateConnectionStringBuilder()
{
return
new
SqlConnectionStringBuilder();
}
public
override
DbDataAdapter CreateDataAdapter()
{
return
new
SqlDataAdapter();
}
public
override
DbDataSourceEnumerator CreateDataSourceEnumerator()
{
return
SqlDataSourceEnumerator.Instance;
}
public
override
DbParameter CreateParameter()
{
return
new
SqlParameter();
}
public
override
CodeAccessPermission CreatePermission(PermissionState state)
{
return
new
SqlClIEntPermission(state);
}
}