用心理解設計模式——工廠方法模式 (Factory Method Pattern)
前置文章: 用心理解設計模式——設計模式的原則
設計模式相關程式碼已統一放至 我的 Github
一、定義
建立型模式之一。
Define an interface for creating an object, but let subclass decide which class to instantiate .
Factory Method lets a class defer instantiation to subclass.
(定義一個用於建立物件的介面,讓子類決定例項化哪一個類。工廠方法使一個類的例項化延遲到其子類)
二、結構解析
工廠方法模式的一般結構有四種角色:抽象工廠、具體工廠、抽象產品、具體產品。
它將 簡單工廠模式(靜態工廠方法模式) 中的工廠類抽象為一個介面(抽象工廠)(這個介面中定義了一個用於建立物件的方法,即工廠方法) 。然後派生出具體工廠類與具體產品類一一對應 ,即, 決定了工廠就意味著決定了產品,最後在具體工廠類中例項化具體產品類。從而使一個類(具體產品類)的例項化延遲到其子類(從抽象工廠類延遲到具體工廠類)。
三、評價
工廠方法模式解決了 簡單工廠模式 (非泛型的實現)違背開閉原則、單一職責原則的問題。
當有產品新增時,不用再需要修改工廠類(抽象工廠類和具體工廠類都不需要修改),而是新增一個與之對應的具體工廠類。
四、實現
//獨立負責一個產品的工廠方法 namespace FactoryMethod { //抽象產品類 public abstract class Product { } public class ConcreteProduct1 : Product { } public class ConcreteProduct2 : Product { } //可擴充套件新的具體產品 //... //抽象工廠類 public abstract class Creator { //定義建立物件的公共介面 public abstract Product FactorMethod(); } //具體工廠類1, 只用來生產產品1 public class ConcreteCreator1 : Creator { public override Product FactorMethod() { return new ConcreteProduct1(); } } //具體工廠類2,只用來生產產品2 public class ConcreteCreator2 : Creator { public override Product FactorMethod() { return new ConcreteProduct2(); } } public class Client { private void Main() { ConcreteCreator1 factory1 = new ConcreteCreator1(); ConcreteCreator2 factory2 = new ConcreteCreator2(); factory1.FactorMethod(); factory2.FactorMethod(); } } }
缺點:工廠方法模式中,具體工廠類直接依賴具體產品類。違背依賴倒置原則(高層模組不應該依賴低層模組,它倆都應該依賴低層模組的抽象) 。
五、泛型工廠方法模式
可以認為泛型T和Object型別一樣,是所有型別的抽象基類。
這樣,具體工廠類(高層模組)將只依賴泛型T(低層模組的抽象基類),並且當產品新增時,也不需要任何改動。
具體實現如下:
抽象工廠類中定義一個用於建立產品物件的公共泛型介面,泛型T 約束為抽象產品類。
實際工廠類繼承抽象工廠類,並實現這個泛型介面,通過反射對T進行例項化。
using System;
//泛型工廠方法
namespace FactoryMethod.GenericFunction
{
//抽象產品類
public abstract class Product { }
//具體產品類
public class ConcreteProduct1 : Product { }
public class ConcreteProduct2 : Product { }
//可擴充套件新的具體產品
//...
//抽象工廠類
public abstract class Creator
{
//定義建立物件的公共介面
public abstract T FactorMethod<T>() where T : Product;
}
//具體工廠類
public class ConcreteCreator : Creator
{
//實現建立物件的公共介面
public override T FactorMethod<T>()
{
return Activator.CreateInstance<T>();
}
}
public class Client
{
private void Main()
{
//建造工廠
ConcreteCreator factory = new ConcreteCreator();
//建立具體產品1
factory.FactorMethod<ConcreteProduct1>();
//建立具體產品2
factory.FactorMethod<ConcreteProduct2>();
}
}
}