工廠方法(Factory Method)

    內容表格
    沒有標頭

    版本為 21:00, 23 Nov 2024

    到這個版本。

    返回到 版本存檔.

    查閱目前版本

    這個模式的定義:
    定義一個用於創建物件的介面, 讓子類別決定要實例化哪一個類別. 工廠方法讓一個類別的實例化遞延到其子類別.
    Define an interface for creating an object, but let subclasses decide wihich class to instantiate. Factory Method lets a class defer instantiation to subclasses.
    從上段語意摘要出的兩個重點:
    1. 創建物件的介面
    2. 讓一個類別的實例化遞延到其子類別
    工廠方法非常有用也常常被實用, 來看看下圖所示:
    500px-FactoryMethod.svg.png

    工廠的目的是用來產生產品, 產品則是服務客戶. Creator通常是一個抽象, 他可以對相關的具象類別產生約束力. 來看看下面的代碼範例:
    201203221601_dp_factorymethod.gif

    這是一個非常簡單的範例, 一個IDbConnectionFactory抽象包含了CreateConnection方法的簽章, 這個方法會對其相關的具象類別產生約束性, 良好的設計可以提高內聚力. 從範例可以非常清楚的看出相關的具象類別用途只用來產出DbConnection的資料庫連線物件, 並且返回.
    對應到第一張的UML圖, factoryMethod的操作限制了ConcreteCreator的使用. 還有一個重點就是, 可以看出真正的實例化並不是在抽象發生, 抽象不允許相關的實作, 但是我們可以利用具象類別對抽象進行實作. MsSqlDbConnectionFactory正是對IDbConnectionFactory的CreateDbConnection方法進行了實作. 所以真正的產品產生會遞延到相關具象子類別.
    透過工廠方法可以產生各種不同的工廠, 這些工廠用以產生不同的產品. 根據前面的範例, 我想擴充一個OLEDB用的連線物件, 只要另外產生出專門用於OLEDB連線物件的工廠即可, 如下代碼範例所示:
    201203221619_dp_factorymethod.gif

    可以看出同一用途的工廠, 但是結果卻是不一樣, 一個是用來產生MS SQL的連線; 另一個則是OLEDB的連線, 彼此完全不相關. 這意味著在良好的設計下, 工廠商法可以產生絕佳的擴展性.
    在Client實際的應用下, Client只需要知道有工廠方法對應的簽章存在就好, 其細節並不是重點, 也並不需要知道. 這完全封裝(隱藏)了真正的運作過程, 降低了耦合. 來看看如下的代碼範例:
    201203221633_dp_factorymethod.gif
    我在Page_Load的樣板方法調用了上面範例的連線工廠物件, Client端的Page_Load並不需要CreateDbConnection方法的細節為何. 他僅需要知道有這個方法存在並且可以使用即可. 

    實務案例: ADO.NET相關物件(ADO.NET的資料庫連線物件)

    在ADO.NET中, 可以使用Connection物件進行對database的連線通訊, 來看看他的類別結構, 如下圖所示:
    201203221643_dp_factorymethod.gif

    從上圖可以看到關鍵性的DbConnection, 他是一個抽象. 他分別繼承了一個類別和兩個介面, 可以關注到一個上層的介面: IDbConnection. 這個介面的抽象主要提供基礎的存取屬性和方法以供次類別實作. IDbConnection會對其下的子類別產生一定程度的約束力, DbConnection則是對這個抽象的豐富化, 這個豐富化的抽象提供更多的存取屬性和方法, 目前微軟於ADO.NET提供了幾種對DbConnection的實作, 從上圖來看共有五種. 對泛生類別來說, DbConnection是可以提供創建物件的一個介面, 其相關的實作會遞延到具象類別實現. 例如來看看SqlConnection的具象類別.
    201203230852_dp_factorymethod.gif

    Powered by MindTouch Core