Factory Pattern

我們如果需要依條件建構不同型別的物件,我們可能寫下這樣的程式碼:

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的感覺還蠻不錯的。