前面我們講述了簡單工廠模式,提到其缺點是系統難以擴展,一旦添加新產品就不得不修改簡單工廠方法,這樣造成簡單工廠方法的實現邏輯過於複雜。本節介紹的工廠方法模式可以解決這個問題。
一、定義
定義一個用於創建對象的接口,讓子類決定實例化哪一個類。工廠方法使一個類的實例化延遲到其子類。
二、結構圖
三、實例
與簡單工廠一致,我們先構建運算類,然後各運算子類繼承該基類
public class Operation
{
public double NumberA
{
get;
set;
}
public double NumberB
{
get;
set;
}
public virtual double GetResult( )
{
double result = 0;
return result;
}
}
public class OperationAdd : Operation
{
public override double GetResult( )
{
double result = 0;
result = NumberA + NumberB;
return result;
}
}
public class OperationSub : Operation
{
public override double GetResult( )
{
double result = 0;
result = NumberA - NumberB;
return result;
}
}
public class OperationMul : Operation
{
public override double GetResult( )
{
double result = 0;
result = NumberA * NumberB;
return result;
}
}
public class OperationDiv : Operation
{
public override double GetResult( )
{
double result = 0;
result = NumberA / NumberB;
return result;
}
}
之前簡單工廠模式的做法是:將所有的負責運算的對象集中在一起,構成一個生產運算法則的類,然後通過該類去實現各種運算,如下所示:
public class OperationFactory
{
/// <summary>
/// 簡單工廠模式:負責生產對象的一個類,本例負責生產運算對象
/// </summary>
/// <param name="operate"></param>
/// <returns></returns>
public static Operation createOperation( string operate )
{
Operation oper = null;
switch(operate)
{
case "+":
oper = new OperationAdd( );
break;
case "-":
oper = new OperationSub( );
break;
case "*":
oper = new OperationMul( );
break;
case "/":
oper = new OperationDiv( );
break;
}
return oper;
}
}
static void Main( string[ ] args )
{
Operation oper;
string str_oper = "+";
oper = OperationFactory.createOperation( str_oper );
oper.NumberA = 1;
oper.NumberB = 2;
double result = oper.GetResult( );
Console.WriteLine( "{0} {1} {2} = {3}", oper.NumberA, str_oper, oper.NumberB, result );
Console.Read( );
}
這種運算方式的邏輯結構圖如下:
而工廠方法模式,它的實現是把具體產品的創建推遲到子類中,此時工廠類不再負責所有產品的創建,而只是給出具體工廠必須實現的接口,這樣工廠方法模式就可以允許系統不修改工廠類邏輯的情況下來添加新產品,這樣也就克服了簡單工廠模式中缺點。
如下所示,先構建一個工廠接口:
//先構建一個工廠接口
interface IFactory
{
Operation CreateOperation( );
}
然後根據運算種類各建一個具體工廠去實現這個接口:
public class AddFactory : IFactory
{
public Operation CreateOperation( )
{
return new OperationAdd( );
}
}
public class SubFactory : IFactory
{
public Operation CreateOperation( )
{
return new OperationSub( );
}
}
public class MulFactory : IFactory
{
public Operation CreateOperation( )
{
return new OperationMul( );
}
}
public class DivFactory : IFactory
{
public Operation CreateOperation( )
{
return new OperationDiv( );
}
}
最後,各運算工廠實現自己的運算方法:
static void Main( string[ ] args )
{
IFactory operFactory = new AddFactory( );
Operation oper = operFactory.CreateOperation( );
oper.NumberA = 1;
oper.NumberB = 2;
double result = oper.GetResult( );
Console.WriteLine( "{0} {1} {2} = {3}", oper.NumberA, "+", oper.NumberB, result );
Console.Read( );
}
實現結構圖:
四、總結
工廠方法模式實現時,客戶端需要決定實例化哪一個工廠來實現運算類,選擇判斷的問題還是存在,也就是說,工廠方法把簡單工廠的內部邏輯判斷移動到客戶端代碼進行。
使用工廠方法實現的系統,如果系統需要添加新產品時,我們可以利用多態性來完成系統的擴展,對於抽象工廠類和具體工廠中的代碼都不需要做任何改動。
工廠方法模式是爲了克服簡單工廠模式的缺點而設計出來的,簡單工廠模式的工廠類隨着產品類的增加需要增加額外的代碼),而工廠方法模式每個具體工廠類只完成單個實例的創建,所以它具有很好的可擴展性。但是在現實生活中,一個工廠只創建單個產品這樣的例子很少,因爲現在的工廠都多元化了,一個工廠創建一系列的產品,如果我們要設計這樣的系統時,工廠方法模式顯然在這裏不適用,不過抽象工廠模式可以很好地解決一系列產品創建的問題。我們在下一章節進行介紹。