一句話解釋:
實體類和工廠類均為單獨實現,不影響已實現的類,方便擴充套件。
工廠方法模式(Factory Method Pattern)是一種建立型模式,它允許使用者端通過工廠方法來建立物件,而不是直接使用建構函式。這樣可以讓使用者端程式碼更加靈活,同時保持實現的獨立性。工廠方法可以返回同一類的物件,也可以返回不同的類物件。
一個比喻:(班主任與班級)
一個班級對應一個班主任,當插班生超額時,則需要重新組成一個班級,那麼此時就需要完成一個班級的各種條件,比如一個新的教室、班主任、班級編號等,當然這個新增的班級對原有的多個班級無影響。
優點:
缺點:
總之,工廠方法模式是一種常用且有效的設計模式,可以提高程式的靈活性和可延伸性,但也需要在實際開發中根據具體情況進行權衡和應用。
使用場景舉例:
如下範例,先定義產品介面 IProduct 和工廠介面 IFactory,再分別進行實現:
#region 定義介面
interface IProduct
{
void Use();
}
// 定義工廠介面
interface IFactory
{
IProduct CreateProduct();
}
#endregion
#region 產品 A
// 實現產品介面的具體產品類
class ConcreteProductA : IProduct
{
public void Use()
{
Console.WriteLine("使用具體產品 A");
}
}
// 實現工廠介面的具體工廠類
class ConcreteFactoryA : IFactory
{
public IProduct CreateProduct()
{
return new ConcreteProductA();
}
}
#endregion
#region 產品 B
class ConcreteProductB : IProduct
{
public void Use()
{
Console.WriteLine("使用具體產品 B");
}
}
class ConcreteFactoryB : IFactory
{
public IProduct CreateProduct()
{
return new ConcreteProductB();
}
}
#endregion
下邊進行實際的呼叫:
// 工廠方法模式
IFactory factoryA = new ConcreteFactoryA();
IProduct productA1 = factoryA.CreateProduct(); // 將物件的建立進行了封裝
IProduct productA2 = factoryA.CreateProduct();
productA1.Use();
productA2.Use();
IFactory factoryB = new ConcreteFactoryB();
IProduct productB = factoryB.CreateProduct();
productB.Use();
// 不用工廠方法模式的寫法
ConcreteProductA concreteProductA1 = new ConcreteProductA(); // 直接建立物件
concreteProductA1.Use();
ConcreteProductA concreteProductA2 = new ConcreteProductA();
concreteProductA2.Use();
ConcreteProductB concreteProductB = new ConcreteProductB();
concreteProductB.Use();
由以上程式碼可見:通過工廠方法模式的實現,將物件的建立進行了封裝,程式碼邏輯更清晰易讀,當需要新增、刪除或修改某個產品時,只需修改具體工廠類即可,既方便又安全。
依賴注入(Dependency Injection,簡稱DI)實際上是工廠方法模式的一種變體,通常與工廠方法模式一起使用。依賴注入可以幫助我們實現物件的建立和管理,使得物件的建立過程更加靈活和可控。
下面一個範例,在建立了語言介面 ILanguage、語言工廠抽象類 LanguageFactory 並實現後,又建立了一個 ClientCode 類來封裝使用者端程式碼的實現,並使用建構函式將具體工廠類作為引數傳遞給該類。使用者端程式碼可以通過呼叫 Speak() 方法來建立相應的產品物件,並執行相關方法。
// 抽象語言類
public interface ILanguage {
void Speak();
}
// 英語類
public class English : ILanguage {
public void Speak() {
Console.WriteLine("Speak English.");
}
}
// 中文類
public class Chinese : ILanguage {
public void Speak() {
Console.WriteLine("說中文。");
}
}
// 工廠方法抽象類
public abstract class LanguageFactory {
public abstract ILanguage CreateLanguage();
}
// 英語工廠
public class EnglishFactory : LanguageFactory {
public override ILanguage CreateLanguage() {
return new English();
}
}
// 中文工廠
public class ChineseFactory : LanguageFactory {
public override ILanguage CreateLanguage() {
return new Chinese();
}
}
// 使用者端程式碼
public class ClientCode {
private readonly LanguageFactory _factory;
public ClientCode(LanguageFactory factory) { // 依賴注入 LanguageFactory
_factory = factory;
}
public void Speak() {
ILanguage language = _factory.CreateLanguage();
language.Speak();
}
}
// 使用範例
static void Main(string[] args)
{
ClientCode code1 = new ClientCode(new EnglishFactory()); // 依賴注入:英語工廠
code1.Speak(); // Speak English.
ClientCode code2 = new ClientCode(new ChineseFactory()); // 依賴注入:中文工廠
code2.Speak(); // 說中文。
}
當然,如果後續有擴充套件需求,比如再新建一個俄語實現:
(只需增加兩個獨立的實現:語言介面 ILanguage、語言工廠抽象類 LanguageFactory)
// 俄語類
public class Russian : ILanguage
{
public void Speak()
{
Console.WriteLine("По-русски.");
}
}
// 俄語工廠
public class RussianFactory : LanguageFactory
{
public override ILanguage CreateLanguage()
{
return new Russian();
}
}
然後直接使用,注入俄語工廠new RussianFactory()
即可輸出俄語,而對原有的實現沒有任何影響。
ClientCode code3 = new ClientCode(new RussianFactory()); // 依賴注入:俄語工廠
code3.Speak();
實際輸出,見第三行:
實際上在 .net 框架中,還有許多類似的用法,例如:
方式都是類似的,詳情自行檢視原始碼吧。
本文來自部落格園,作者:橙子家,微訊號:zfy1070491745,有任何疑問歡迎溝通,一起成長。
轉載本文請註明原文連結:https://www.cnblogs.com/czzj/p/SJMSLL_FactoryMethod.html