抽象工廠學(xué)習(xí)筆記
1.1.1 摘要
抽象工廠模式:允許客戶(hù)使用抽象的接口來(lái)創(chuàng)建一系列相關(guān)的產(chǎn)品,而無(wú)需要知道實(shí)際產(chǎn)出的具體產(chǎn)品是什么。這樣一來(lái),客戶(hù)就從具體的產(chǎn)品中被解耦出來(lái)。這種模式適用于產(chǎn)品對(duì)象的數(shù)目和種類(lèi)不變,而具體產(chǎn)品系列之間存在不同或者容易變化的情況。
關(guān)鍵字:依賴(lài)抽象,不要依賴(lài)具體類(lèi),OCP
使用率:
high

圖
1.1.2 參與類(lèi)或接口作用
AbstractFactory (UIAbstractFactory):定義一個(gè)接口用來(lái)創(chuàng)建抽象產(chǎn)品,擔(dān)任這個(gè)角色的是工廠方法模式的核心,它是與應(yīng)用系統(tǒng)商業(yè)邏輯無(wú)關(guān)的。
ConcreteFactory (MacUIFactory, WinUIFactory):這個(gè)角色直接在客戶(hù)端的調(diào)用下創(chuàng)建產(chǎn)品的實(shí)例。這個(gè)角色含有選擇合適的產(chǎn)品對(duì)象的邏輯,而這個(gè)邏輯是與應(yīng)用系統(tǒng)的商業(yè)邏輯緊密相關(guān)的。
AbstractProduct (IButton, IBorder):擔(dān)任這個(gè)角色的類(lèi)是工廠方法模式所創(chuàng)建的對(duì)象的父類(lèi),或它們共同擁有的接口。
Product (WinBotton, MacBotton, WinBorder, MacBorder):抽象工廠模式所創(chuàng)建的任何產(chǎn)品對(duì)象都是某一個(gè)具體產(chǎn)品類(lèi)的實(shí)例。這是客戶(hù)端最終需要的東西,其內(nèi)部一定充滿了應(yīng)用系統(tǒng)的商業(yè)邏輯。
Client (UIClient):調(diào)用AbstractFactory和AbstractProduct的接口。




圖
1.1.3 模式實(shí)現(xiàn)技術(shù)
利用設(shè)計(jì)模式可以使我們代碼更加靈活,更容易擴(kuò)展,更容易維護(hù)。各種面向?qū)ο蟮某绦蛟O(shè)計(jì)語(yǔ)言都提供了基本相同的機(jī)制:比如類(lèi)、繼承、派生、多態(tài)等等。同時(shí).Net Framework提供我們一種重要的特性—反射,這樣我們可以動(dòng)態(tài)的創(chuàng)建對(duì)象的實(shí)例,而且只需修改配置文件就可以創(chuàng)建不同實(shí)例,并且無(wú)需重新編譯整個(gè)程序。除了使用反射我們還可以使用微軟Enterprise Library提供的Unity進(jìn)行依賴(lài)注入把UIClient從UIAbstractFactory和AbstractFactory解耦出來(lái)。
方法一:
// CreateInstance有多個(gè)重載方法
Activator.CreateInstance(Type.GetType("命名空間.類(lèi)名稱(chēng)"));
方法二:
Assembly.Load("程序集名稱(chēng)").CreateInstance("命名空間.類(lèi)名稱(chēng)");
方法三:
使用IoC容器進(jìn)行依賴(lài)注入。
1.1.4 抽象工廠的簡(jiǎn)單實(shí)現(xiàn)
View Code
namespace UnityTestApp
{
class Program
{
public static void Main()
{
UIClient myClient = new UIClient(OS.Win);
myClient.PaintUI();
Console.ReadKey();
}
}
/// <summary>
/// 客戶(hù)端
/// </summary>
public class UIClient
{
private IButton button;
private IBorder border;
private UIAbstractFactory myFactory = null;
public UIClient(OS osName)
{
//使用反射機(jī)制
string concreteFactroyName = this.GetType().Namespace.ToString() + "." + osName.ToString() + "UIFactory";
this.myFactory = Activator.CreateInstance(Type.GetType(concreteFactroyName)) as UIAbstractFactory;
//具體工廠引用只出現(xiàn)一次,使得產(chǎn)品易于交換,有利于產(chǎn)品一致性
this.button = this.myFactory.CreateButton();
this.border = this.myFactory.CreateBorder();
}
public void PaintUI()
{
this.button.PaintControl();
this.border.PaintControl();
}
}
/// <summary>
/// UI抽象工廠
/// </summary>
public abstract class UIAbstractFactory
{
public abstract IButton CreateButton();
public abstract IBorder CreateBorder();
}
/// <summary>
/// WinUI具體工廠
/// </summary>
public class WinUIFactory : UIAbstractFactory
{
public override IButton CreateButton()
{
return new WinButtion();
}
public override IBorder CreateBorder()
{
return new WinBorder();
}
}
/// <summary>
/// MacUI抽象工廠
/// </summary>
public class MacUIFactory : UIAbstractFactory
{
public override IButton CreateButton()
{
return new MacButton();
}
public override IBorder CreateBorder()
{
return new MacBorder();
}
}
/// <summary>
/// 抽象產(chǎn)品Button
/// </summary>
public interface IButton
{
void PaintControl();
}
/// <summary>
/// 具體產(chǎn)品
/// </summary>
public class WinButtion : IButton
{
public void PaintControl()
{
Console.WriteLine("Win button.");
}
}
/// <summary>
/// 具體產(chǎn)品
/// </summary>
public class MacButton : IButton
{
public void PaintControl()
{
Console.WriteLine("Mac button.");
}
}
/// <summary>
/// 抽象產(chǎn)品
/// </summary>
public interface IBorder
{
void PaintControl();
}
/// <summary>
/// 具體產(chǎn)品
/// </summary>
public class WinBorder : IBorder
{
public void PaintControl()
{
Console.WriteLine("Win border.");
}
}
/// <summary>
/// 具體產(chǎn)品
/// </summary>
public class MacBorder : IBorder
{
public void PaintControl()
{
Console.WriteLine("Mac border.");
}
}
/// <summary>
/// 枚舉產(chǎn)品種類(lèi)
/// </summary>
public enum OS
{
Win,
Mac,
Motif
}
}
代碼明細(xì):
- 關(guān)于抽象類(lèi)和接口的使用,一般在沒(méi)有具體代碼實(shí)現(xiàn)情況下應(yīng)該多使用接口
- 抽象工程將產(chǎn)品的創(chuàng)建推遲到它的具體工廠子類(lèi)中

1.1.5 .NET中抽象工廠的實(shí)現(xiàn)
我們?cè)?NET Framework類(lèi)庫(kù)中查找”Factory”關(guān)鍵字可以找很多相關(guān)的類(lèi),其中就有我們熟悉ADO.NET中包含兩個(gè)抽象工廠類(lèi)它們提供獨(dú)立數(shù)據(jù)訪問(wèn)方式,它們分別是:DbProviderFactory和DbProviderFactories。
DbProviderFactory抽象工廠創(chuàng)建抽象的數(shù)據(jù)存儲(chǔ)方法(DbCommand, DbConnection, DbCommand等方法)。
OdbcFactory,OleDbFactory和SqlClientFactory具體工廠用來(lái)創(chuàng)建對(duì)應(yīng)不同數(shù)據(jù)庫(kù)的數(shù)據(jù)存儲(chǔ)方法。
DbProviderFactories用生產(chǎn)抽象工廠,所以說(shuō)它是抽象工廠的工廠。
//。NET 中抽象工廠實(shí)現(xiàn)
public abstract class DbProviderFactory
{
// Methods
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);
// Properties
public virtual bool CanCreateDataSourceEnumerator { get; }
}

1.1.6 抽象工廠的優(yōu)缺點(diǎn)
優(yōu)點(diǎn)
-
分離具體類(lèi),抽象工廠創(chuàng)建一系列對(duì)象的類(lèi),封裝創(chuàng)建產(chǎn)品對(duì)象的職責(zé)和過(guò)程,它實(shí)現(xiàn)了客戶(hù)和類(lèi)的分離。
-
易于創(chuàng)建不同系列的產(chǎn)品,當(dāng)客戶(hù)類(lèi)要?jiǎng)?chuàng)建不同系列的產(chǎn)品適合執(zhí)行修改具體工廠就OK了
-
有利于產(chǎn)品的一致性,當(dāng)一個(gè)系列的產(chǎn)品對(duì)象被設(shè)計(jì)成一起工作時(shí),一個(gè)應(yīng)用一次只能使用同一個(gè)系列中的對(duì)象,這一點(diǎn)很重要,而抽象工廠很容易實(shí)現(xiàn)這一點(diǎn)。
缺點(diǎn)
-
難以擴(kuò)展抽象工廠生產(chǎn)新的產(chǎn)品,假設(shè)我們修改抽象工廠生產(chǎn)新的產(chǎn)品,那么這將導(dǎo)致其他類(lèi)的級(jí)聯(lián)修改不便于維護(hù)。
|
|
關(guān)于作者:[作者]:
JK_Rush從事.NET開(kāi)發(fā)和熱衷于開(kāi)源高性能系統(tǒng)設(shè)計(jì),通過(guò)博文交流和分享經(jīng)驗(yàn),歡迎轉(zhuǎn)載,請(qǐng)保留原文地址,謝謝。 |

抽象工廠模式:允許客戶(hù)使用抽象的接口來(lái)創(chuàng)建一系列相關(guān)的產(chǎn)品,而無(wú)需要知道實(shí)際產(chǎn)出的具體產(chǎn)品是什么。這樣一來(lái),客戶(hù)就從具體的產(chǎn)品中被解耦出來(lái)。這種模式適用于產(chǎn)品對(duì)象的數(shù)目和種類(lèi)不變,而具體產(chǎn)品系列之間存在不同或者容易變化的情況。

浙公網(wǎng)安備 33010602011771號(hào)