public interface IFactory<T>
{
T Create();
}
這個工廠生產一個T類型的對象。當你實現此工廠時,應該讓T為抽象產品的類型——即產品通用的基類。比如我們可以實現一個採用無參數建構函式來建立對象的OpNewFactory實現:
public class OpNewFactory<TAbstractProduct, TProduct> : IFactory<TAbstractProduct>
where TProduct : TAbstractProduct, new()
{
public TAbstractProduct Create()
{
return new TProduct();
}
}
從此例子可以看出,你應該僅實現抽象類別型的IFactory介面,並產生具體類型。現在我們做完了單一產品的Factory 方法模板,就要開始定義生產多個產品的抽象工廠介面了。.NET泛型支援按型別參數個數進行重載,就是說,我們可以定義生產一個、兩個、三個……等多種數目的抽象工廠介面,而使用同一個名字。(汗吧,這就是所謂支援“任意數目”的手法)這裡免不了要拷貝代碼,不過別擔心,純拷貝而已,使用的時候可是非常舒心的哦。我們以生產兩種產品類型的抽象工廠為例介紹。能不能定義成這樣呢?
public sealed class TypeToken<T>
{
static private TypeToken<T> instanceValue = new TypeToken<T>();
static public TypeToken<T> Instance
{
get { return instanceValue; }
}
public T1 Create(TypeToken<T1> token)
{
return factory1.Create();
}
public T2 Create(TypeToken<T2> token)
{
return factory2.Create();
}
}
public static class ConcretFactory
{
public static ConcreteFactory<T1, T2> NewFactory<T1, T2>(IFactory<T1> f1, IFactory<T2> f2)
{
return new ConcreteFactory<T1, T2>(f1, f2);
}
}
注意,我又聲明了一個沒有型別參數的ConcretFactory類,用一個靜態方法來產生泛型ConcretFactory的執行個體,這是因為使用泛型方法可以推測型別參數,使得我們可以不必輸入角括弧或Of語句,而泛型類則沒有這個功能。現在大功告成!我們用一個例子來示範這個泛型抽象工廠的工作情況。現在假設我們需要一個生產PC的抽象工廠,需要生產兩種抽象產品:處理器和記憶體。處理器和記憶體的抽象和具體實現如下:
Processor 和 Ram
public abstract class Processor
{
public abstract string Model { get; }
}
public abstract class Ram
{
public abstract int Frequency { get;}
}
public class PentiumProcessor : Processor
{
public override string Model
{
get { return "Pentium Extreme Edition 955"; }
}
}
public class AthlonProcessor : Processor
{
public override string Model
{
get { return "Athlon 64 X2 FX-60"; }
}
}
public class DDRRam : Ram
{
public override int Frequency
{
get { return 400; }
}
}
public class DDR2Ram : Ram
{
public override int Frequency
{
get { return 533; }
}
}
下面的代碼示範了如何隨心所欲產生想要的抽象工廠介面以及快速從現有單一產品工廠組合成特定的具體工廠實現。
class Program
{
static IAbstractFactory<Processor, Ram> ComputerFactory(string type)
{
if (type == "Intel")
{
return ConcretFactory.NewFactory( new OpNewFactory<Processor, PentiumProcessor>(),
new OpNewFactory<Ram, DDR2Ram>());
}
else if (type == "AMD")
{
return ConcretFactory.NewFactory( new OpNewFactory<Processor, AthlonProcessor>(),
new OpNewFactory<Ram, DDRRam>());
}
//unknown type
return null;
}
static void Main(string[] args)
{
//Yield a computer of Intel
IAbstractFactory<Processor, Ram> factory1 = ComputerFactory("Intel");