php設計模式總結-工廠模式

王滔發表於2014-03-11

使用工廠模式的目的或目標?

工廠模式的最大優點在於建立物件上面,就是把建立物件的過程封裝起來,這樣隨時可以產生一個新的物件。
減少程式碼進行復制粘帖,耦合關係重,牽一髮動其他部分程式碼。

通俗的說,以前建立一個物件要使用new,現在把這個過程封裝起來了。
假設不使用工廠模式:那麼很多地方呼叫類a,程式碼就會這樣子建立一個例項:new a(),假設某天需要把a類的名稱修改,意味著很多呼叫的程式碼都要修改。



工廠模式的優點就在建立物件上。
工廠模式的優點就在建立物件上。建立一個工廠(一個函式或一個類方法)來製造新的物件,它的任務就是把物件的建立過程都封裝起來,
建立物件不是使用new的形式了。而是定義一個方法,用於建立物件例項。

每個類可能會需要連線資料庫。那麼就將連線資料庫封裝在一個類中。以後在其他類中通過類名:

為什麼引入抽象的概念?
想一想,在現實生活中,當我們無法確定某個具體的東西的時候,往往把一類東西歸於抽象類別。
工廠方法:
比如你的工廠叫做“香菸工廠”,那麼可以有“七匹狼工廠”“中華工廠”等,但是,這個工廠只生廠一種商品:香菸;
抽象工廠:無法描述它到底生產什麼產品,它生產很多型別的產品(所以抽象工廠就會生成子工廠)。
你的工廠是綜合型的,是生產“一系列”產品,而不是“一個”,比如:生產“香菸”,還有“啤酒”等。然後它也可以有派生出來的具體的工廠,但這些工廠都是生產這一系列產品,只是可能因為地域不一樣,為了適應當地人口味,味道也不太一樣。
工廠模式:理解成只生成一種產品的工廠。比如生產香菸的。
工廠方法:工廠的一種產品生產線 。比如鍵盤的生成過程。



別人會反駁:吃飽了沒事幹,一定要修改類名稱呢?這個說不定。一般都不會去修改類名稱。






其實工廠模式有很多變體,抓住精髓才是關鍵:只要是可以根據不同的引數生成不同的類例項,那麼就符合工廠模式的設計思想。

這樣子讓我聯想到框架中經常會有負責生成具體類例項的方法供呼叫。

由於前面使用過phpcms,用phpcms的來幫助理解,更加好,如下:


pc_base:load_app_class("order"');//引數名稱就是類名稱。將會生成得到order這個例項。傳遞不同的引數得到不同的類例項,這個就符合工廠模式。



pc_base:load_app_class("comment"');//生成一個comment類例項

//當然load_app_class這個方法裡面還會結合了單件模式的思想。避免呼叫n次,就重複建立n個相同的例項









工廠模式我想到的一個典型的應用就是:php可能要連結mysql,也可能要連結sqlserver,還有其他什麼資料庫。那麼做一個抽象的資料庫類,

這個類就是一個工廠類,專門負責產生不同的物件。

這樣子做很方便擴充套件。我們在直接連結資料庫的時候,不是使用程式碼new Mysql($host,$username,$password,$dbname)的形式

而可以動態生成一個連線資料庫的例項。可以是mysql,也可以是連線oracle的。

class DbFactory
{

function static factory($db_class_name)
{

        $db_class_name = strtolower($db_class_name);

        if (include_once 'Drivers/' . $db_class_name . '.php') {

     
            $classname = 'Driver_' . $db_class_name;
            return new $db_class_name;
        } else {
            throw new Exception ('對應的資料庫類沒找到');
        }


}




}



DbFactory::factory("mysql");

DbFactory::factory("oracle");



在thinkphp框架中也有對應的實現:

Db.class.php就是一個工廠類(也可以叫做資料庫中間層,之所以叫做中間層,是因為可以操作mysql、oracle等各資料庫。而這個類就是中間層作用,遮蔽掉具體的實現。讓程式設計師可以不改動原來的查詢程式碼。中間層來對接mysql、oracle等資料庫。



Db.class.php中有個factory()方法來建立不同的資料庫例項

    public function factory($db_config='') {
        // 讀取資料庫配置
        $db_config = $this->parseConfig($db_config);
        if(empty($db_config['dbms']))
            throw_exception(L('_NO_DB_CONFIG_'));
        // 資料庫型別
        $this->dbType = ucwords(strtolower($db_config['dbms']));
        $class = 'Db'. $this->dbType;
        if(is_file(CORE_PATH.'Driver/Db/'.$class.'.class.php')) {
            // 內建驅動
            $path = CORE_PATH;
        }else{ // 擴充套件驅動
            $path = EXTEND_PATH;
        }
        // 檢查驅動類
        if(require_cache($path.'Driver/Db/'.$class.'.class.php')) {
            $db = new $class($db_config);
            // 獲取當前的資料庫型別
            if( 'pdo' != strtolower($db_config['dbms']) )
                $db->dbType = strtoupper($this->dbType);
            else
                $db->dbType = $this->_getDsnType($db_config['dsn']);
            if(APP_DEBUG)  $db->debug    = true;
        }else {
            // 類沒有定義
            throw_exception(L('_NOT_SUPPORT_DB_').': ' . $db_config['dbms']);
        }
        return $db;
    }





還有做支付介面的時候,未來可能對應不同的支付閘道器:支付寶、財付通、網銀線上等。方便未來擴充套件,設計成工廠模式。定一個專門生產閘道器介面的工廠,抽象出來,做成介面形式,讓所有的子類都要實現它的介面。以後加一個支付方式,要使用哪一種支付方式,改變一下引數即可。


書籍<php權威程式設計>(英文名稱為PHP 5 Power Programming)也提到一個工廠模式的例子,學到一招:在為使用者註冊的時候,分為很多種角色的使用者。比如冊使用者,匿名使用者、管理員使用者等。完全使用可以使用工廠的思想來實現,程式碼也容易維護,為每種角色可以生成操作的類。

定義以下幾個類:

UserFactory 使用者工廠類,負責生成不同的使用者類
User:使用者類的基類,所有使用者類都是繼承這個類
不同角色的類:註冊使用者類、匿名使用者類、管理員使用者類

 

 

總結結束,歡迎指正!

相關文章