我們如果需要依條件建構不同型別的物件,我們可能寫下這樣的程式碼:
Base obj = null;
switch (condition)
{
case XX:
obj = new A();
break;
case YY:
obj = new B();
break;
}
我們如果需要依條件建構不同型別的物件,我們可能寫下這樣的程式碼:
Base obj = null;
switch (condition)
{
case XX:
obj = new A();
break;
case YY:
obj = new B();
break;
}
obj.DoSomeThing();
這樣的缺點是,如果日後我們再新增一個C類別,我們需要更改程式碼。
Base obj = null;
switch (condition)
{
case XX:
obj = new A();
break;
case YY:
obj = new B();
break;
case ZZ: // 增加C類別的處理
obj = new C();
break;
}
obj.DoSomeThing();
為了避免這樣的擴充會影響使用端的程式碼,我們可以這樣做:
定義Factory類別,
static class Factory
{
public static Base CreateBaseObject(T condition)
{
switch (condition)
{
case XX:
return new A();
break;
case YY:
return new B();
break;
case ZZ: // 增加C類別的處理
return new C();
break;
}
}
}
使用Factory來建構物件,
Base obj = Factory.CreateBaseObject(condition);
obj.DoSomeThing();
如此一來,我們簡化了使用端的程式碼,把變化封裝在Factory類別中。
這樣的情況下,如果我們是一直在同一個專案下擴充Factory的功能,那我們只要一直修改CreateBaseObject方法的內容即可,
不過如果,我們是Release了這個組件,那其擴充性就會停止,沒有方法可以再擴充新的類別。
因應這樣的狀況,我所想到的做法是,我們建立Factory的介面,並讓Factory類別實作這個介面,
interface IFactory
{
public Base CreateBaseObject(T condition);
}
class Factory: IFactory
{
public Base CreateBaseObject(T condition)
{
switch (condition)
{
case XX:
return new A();
break;
case YY:
return new B();
break;
case ZZ: // 增加C類別的處理
return new C();
break;
}
}
}
而使用端的程式碼則變為,
IFactory factory = new Factory();
Base obj = factory.CreateBaseObject(condition);
obj.DoSomeThing();
factory物件的實作,我們可以利用設定及Reflection來指定不同的Factory建構,這樣一來,我們可以指定要使用的工廠物件,並且利用其工廠來建構我們所想要的目標物件。
在研究Enterprise Library的DAAB的時候,發現了另外一個有趣的作法,
目前的作法,物件的建構規則都是被工廠物件所掌握,
也就是說,工廠物件必須知道物件的建構方法,才能建構物件,
而這個新的想法是,
我們只要讓物件"告知"工廠"自己"如何建構,這樣一來,我們在擴充新的類別的時候,
我們可以集中精神在類別的功能上,而不用費神在工廠的實作上。
而方法是利用一個實作建構方法的介面及Attribute來告知工廠實作方法,
這樣跟Reflection的方式並沒有大差異,我們一樣定一個建構規則才能成功的建構物件,
不過這個方法的特色是,第一,我們不必依賴比較沒有強制力的建構子來指定建構方法,
第二是,Reflection的目標不同,Attribute所Reflection的目標是實作建構方法的物件,這個物件相對上會比較輕量。
目前感覺上,覺得利用Attribute的方式還蠻好用的,另外也學到了一個Attribute的使用時機,
就這樣來說,學習Enterprise Library的感覺還蠻不錯的。