剛開始接觸設(shè)計模式時就常常聽到同事提起工廠模式,那時也看過一些人寫的Blog, 但是往往把注意力放在代碼的編寫上。在這段時間的學(xué)習(xí)中慢慢體會到設(shè)計模式是用來解決一類問題,而不是某些固定的代碼片段。換句話說是解決問題的思想。設(shè) 計模式可以解決模塊的耦合關(guān)系,可以解決因需求變動帶來的問題。程序在第一次編寫時,各個模塊之間可能是緊耦合,但是經(jīng)過代碼重構(gòu),可以將模塊之間變?yōu)樗? 耦合。當(dāng)然,我覺得我們也可以在軟件設(shè)計之初把變化考慮到其中,對于業(yè)務(wù)型軟件設(shè)計,在了解需求后,可以盡可能將其分出主次關(guān)系。也就是主體與枝節(jié)的關(guān) 系。如下圖
對
于工廠模式來說,要求高層模塊變化相對較慢,底層模塊變化相對較快。這樣符合設(shè)計模式中的依賴倒置原則——高層模塊不依賴于底層模塊。換句話說,軟件設(shè)計
是要劃分易變部分和穩(wěn)定部分。這樣在一些枝節(jié)問題發(fā)生變化時,主干不用變化。如果是緊耦合狀態(tài),有可能造成一個地方變化,連帶著很多地方要發(fā)生變化。
工廠模式要解決的是“某個對象”的創(chuàng)建工作,由于需求的變化,這個對象常常面臨著劇烈的變化,但是這個對象擁有的接口相對穩(wěn)定。也就是說:枝節(jié)常常發(fā)生變化,但是枝節(jié)與主干的接口相對穩(wěn)定。
《設(shè)計模式》中是這樣說明:定義一個用于創(chuàng)建對象的接口,讓子類決定實例化那個類。FactoryMethod使得一個類的實例化延遲到子類。
現(xiàn)在看這句話可能有些不明白,我們一會再來分析一下。先來看看工廠模式的大體結(jié)構(gòu)。如下圖:
我們還是用實例化汽車的例子來解釋。對于客戶端程序(ClientApp)如果想要一個汽車的對象,需要調(diào)用生產(chǎn)這個汽車的Factory的對象。當(dāng)然,這個類繼承自一個AbstractFactory基類。而這個Factory類就是《設(shè)計模式》中提到的“子類”,它來決定實例化那個類。
下面我們來具體實現(xiàn)一下代碼,首先,我們需要兩個基類,一個是Car的,一個是Factory的。Factory類型的作用是構(gòu)建Car的對象。代碼如下:
public abstract class AbstractCar
{
public abstract string Run();
public abstract string Stop();
public abstract string Accelerate();
public abstract string Decelerate();
}
public abstract class AbstractFactory
{
public abstract AbstractCar CreateCar();
}
下面,我們來做一個BMW的實現(xiàn)代碼:
public class BMWCar:AbstractCar
{
public override string Run()
{
return "BMW Run";
}
public override string Stop()
{
return "BMW Stop";
}
public override string Accelerate()
{
return "BMW Accelerate";
}
public override string Decelerate()
{
return "BMW Decalerate";
}
}
public class BMWFactory:AbstractFactory
{
public override AbstractCar CreateCar()
{
return new BMWCar();
}
}
這樣我們就可以在客戶端程序得到一個BMW的實例,并使用它的方法:
class Class1
{
/// <summary>
/// 應(yīng)用程序的主入口點。
/// </summary>
[STAThread]
static void
{
AbstractCar car = CreateCarFunc(new BMWFactory ());
Console.Write(car.Run() + "\n");
Console.Write(car.Stop() + "\n");
Console.Write(car.Accelerate() + "\n");
Console.Write(car.Decelerate() + "\n");
Console.Read();
}
public static AbstractCar CreateCarFunc(AbstractFactory factory)
{
return factory.CreateCar();
}
}
在客戶端程序中,我們AbstractFactory的對象來得到Car的對象
結(jié)果如下:
BMW Run
BMW Stop
BMW Accelerate
BMW Decalerate
如果我們需求變了,現(xiàn)在要BORA的對象,那末,我們首先要對程序作一下擴展,先加入BOAR的Car類和Factory類,代碼如下:
public class BORACar:AbstractCar
{
public override string Run()
{
return "BORA Run";
}
public override string Stop()
{
return "BORA Stop";
}
public override string Accelerate()
{
return "BORA Accelerate";
}
public override string Decelerate()
{
return "BORA Decelerate";
}
}
public class BORAFactory:AbstractFactory
{
public override AbstractCar CreateCar()
{
return new BORACar();
}
}
在客戶端程序中,我們只要稍作修改,將BMWFactory的實例化變?yōu)?span lang="EN-US">BORAFactory的實例化就可以,代碼如下:
class Class1
{
/// <summary>
/// 應(yīng)用程序的主入口點。
/// </summary>
[STAThread]
static void
{
AbstractCar car = CreateCarFunc(new BORAFactory());
Console.Write(car.Run() + "\n");
Console.Write(car.Stop() + "\n");
Console.Write(car.Accelerate() + "\n");
Console.Write(car.Decelerate() + "\n");
Console.Read();
}
public static AbstractCar CreateCarFunc(AbstractFactory factory)
{
return factory.CreateCar();
}
}
得到的結(jié)果是:
BORA Run
BORA Stop
BORA Accelerate
BORA Decelerate
Factory Method的幾個要點:
1、Factory Method模式主要用于隔離類對象的使用者和具體類型之間的耦合關(guān)系。面對一個經(jīng)常變化的具體類型,緊耦合關(guān)系會導(dǎo)致軟件的脆弱。
2、Factory Method模式通過面向?qū)ο蟮氖址?,將所要?chuàng)建的對象工作延遲到子類,從而實現(xiàn)一種擴展的策略,較好的解決了這種緊耦合關(guān)系。