問題:
簡單工廠模式比較適用於事先已經考慮到的可能出現的算法,來構造工廠類實現,如果需要添加新的類,則就需要改變工廠類了,違反開閉原則,簡單的說,簡單公共適應與業務變化不是很劇烈的場景下如,審批業務,設計時可以判斷到的只有“部門經理審批”,“總裁審批”不會過幾天又要加入“組長審批”,去修改工廠類,相對來說變化不是很劇烈的。
在軟件設計中經常面臨着“某個對象”的創建工作,由於需求的變化,這個對象的具體實現經常面臨着劇烈的變化,但是它卻擁有比較穩定的接口。如果我們使用簡單工廠,這樣會不斷地修改工廠類,應對業務變化,違反開閉原則,另外因為實例化產品的判斷邏輯在工廠類中,工廠類會變的越來與臃腫。
定義:
工廠方法模式又稱為工廠模式,也叫虛擬構造器(Virtual Constructor)模式或者多態工廠模式(Polymorphic Factory),定義一個用戶創建對象的接口,讓子類決定實例化哪一個類,工廠方法模式使一個類的實例化延遲到其子類。
意圖:
定義一個用戶創建對象的公共接口,此接口不負責產品的創建不關心產品實例化細節,而是將具體創建工作交給子類去做,這樣做的目的是將類的實例化操作延遲到子類中完成,即由子類來決定究竟應該實例化(創建)哪一個類,使得工廠方法模式可以允許系統在不修改工廠角色的情況下引進新產品。
參與者:
•抽象工廠(Creator)角色:
是工廠方法模式的核心,聲明工廠方法(FactoryMethod),返回一個產品。任何在模式中創建的對象的工廠類必須實現這個接口。
•具體工廠(Concrete Creator)角色:
這是實現抽象工廠接口的具體工廠類,包含與應用程序密切相關的邏輯,由客戶調用,返回一個產品的實例 。
•抽象產品(Product)角色:
工廠方法模式所創建的對象產品的抽象類型。
•具體產品(Concrete Product)角色:
這個角色實現了抽象產品角色所定義的接口。某具體產品有專門的具體工廠創建,它們之間往往一一對應。
UML圖:
實例說明:
諾基亞手機工廠
比如Nokia手機工廠,現在只生產N8,N9兩款手機,如果以后生產N10手機可以不修改現有的生產邏輯可以使用工廠方法,根據不同生產工廠(N8生產車間,N9
生產車間)創建不同的Nokia手機,而且容易加入新型號手機的生產(不修改現有系統)。uml圖如下:
代碼:
/// 手機接口
/// </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 ×××的語句,因為根本就不知道×××是什么。
•簡單工廠模式無法應對業務變化的時候。