問題:
簡單原廠模式比較適用於事先已經考慮到的可能出現的演算法,來構造工廠類實現,如果需要添加新的類,則就需要改變工廠類了,違反開閉原則,簡單的說,簡單公用適應與業務變化不是很劇烈的情境下如,審批業務,設計時可以判斷到的只有“部門經理審批”,“總裁審批”不會過幾天又要加入“組長審批”,去修改工廠類,相對來說變化不是很劇烈的。
在軟體設計中經常面臨著“某個對象”的建立工作,由於需求的變化,這個對象的具體實現經常面臨著劇烈的變化,但是它卻擁有比較穩定的介面。如果我們使用簡單工廠,這樣會不斷地修改工廠類,應對業務變化,違反開閉原則,另外因為執行個體化產品的判斷邏輯在工廠類中,工廠類會變的越來與臃腫。
定義:
Factory 方法模式又稱為原廠模式,也叫虛擬構造器(Virtual Constructor)模式或者多態原廠模式(Polymorphic Factory),定義一個使用者建立對象的介面,讓子類決定執行個體化哪一個類,Factory 方法模式使一個類的執行個體化延遲到其子類。
意圖:
定義一個使用者建立對象的公用介面,此介面不負責產品的建立不關心產品執行個體化細節,而是將具體建立工作交給子類去做,這樣做的目的是將類的執行個體化操作延遲到子類中完成,即由子類來決定究竟應該執行個體化(建立)哪一個類,使得Factory 方法模式可以允許系統在不修改工廠角色的情況下引進新產品。
參與者:
•抽象工廠(Creator)角色:
是Factory 方法模式的核心,聲明Factory 方法(FactoryMethod),返回一個產品。任何在模式中建立的對象的工廠類必須實現這個介面。
•具體工廠(Concrete Creator)角色:
這是實現抽象工廠介面的具體工廠類,包含與應用程式密切相關的邏輯,由客戶調用,返回一個產品的執行個體 。
•抽象產品(Product)角色:
Factory 方法模式所建立的對象產品的抽象類別型。
•具體產品(Concrete Product)角色:
這個角色實現了抽象產品角色所定義的介面。某具體產品有專門的具體工廠建立,它們之間往往一一對應。
UML圖:
執行個體說明:
諾基亞手機工廠
比如Nokia手機工廠,現在只生產N8,N9兩款手機,如果以後生產N10手機可以不修改現有的生產邏輯可以使用Factory 方法,根據不同生產工廠(N8生產車間,N9
生產車間)建立不同的Nokia手機,而且容易加入新型號手機的生產(不修改現有系統)。uml圖如下:
代碼:
/// <summary>
/// 手機介面
/// </summary>
public interface INokiaPhone
{
string GetPhoneName();
}
/// <summary>
/// N8手機具體類
/// </summary>
public class N8Phone : INokiaPhone
{
public string GetPhoneName()
{
return "我是N8";
}
}
/// <summary>
/// N9手機具體類
/// </summary>
public class N9Phone : INokiaPhone
{
public string GetPhoneName()
{
return "我是N9";
}
}
/// <summary>
/// 手機抽象工廠類
/// </summary>
public interface IPhoneFactory
{
INokiaPhone CreateNokiaPhone();
}
/// <summary>
/// N8手機工廠
/// </summary>
public class NokiaN8Factory : IPhoneFactory
{
public INokiaPhone CreateNokiaPhone()
{
return new N8Phone();
}
}
/// <summary>
/// N9手機工廠
/// </summary>
public class NokiaN9Factory : IPhoneFactory
{
public INokiaPhone CreateNokiaPhone()
{
return new N9Phone();
}
}
/// <summary>
/// 用戶端類
/// </summary>
class Program
{
void CreatePhone()
{
IPhoneFactory factory = new NokiaN8Factory();
INokiaPhone phone = factory.CreateNokiaPhone();
phone.GetPhoneName();
}
}
優點:
•建立一個具體產品的細節完全封裝在具體工廠內部,符合高內聚,低耦合
•在系統中加入新產品時,無需修改抽象工廠和抽象產品提供的介面,符合開閉原則,大大提高系統擴充性
缺點:
•每加入一種新產品都要,建立一個產品的工廠(方法)
•Factory模式僅僅局限於一類類(就是說Product是一類,有一個共同的基類),沒辦法為不同類的類提供一個對象建立的介面
應用情景:
•當一個類需要調用另一個類,但是並不(需要)知道具體要執行個體化哪一個具體的子類,希望由它的子類來指定它所建立的對象的時候。這裡的意思為:假設我們在類A中要使用到類B,B是一個抽象父類,在A中並不知道具體要執行個體化那一個B的子類,但是在類A的子類D中是可以知道的。在A中我們沒有辦法直接使用類似於new ×××的語句,因為根本就不知道×××是什麼。
•簡單原廠模式無法應對業務變化的時候。