最初在設計模式一書中,許多設計模式都鼓勵使用鬆散耦合。要理解這個概念,讓我們最好談一下許多開發人員從事大型系統的艱苦曆程。在更改一個程式碼片段時,就會發生問題,系統其他部分 —— 您曾認為完全不相關的部分中也有可能出現級聯破壞。
該問題在於緊密耦合 。系統某個部分中的函數和類嚴重依賴於系統的其他部分中函數和類的行為和結構。您需要一組模式,使這些類能夠相互連信,但不希望將它們緊密綁定在一起,以避免出現聯鎖。
在大型系統中,許多代碼依賴於少數幾個關鍵類。需要更改這些類時,可能會出現困難。例如,假設您有一個從檔案讀取的 User 類。您希望將其更改為從資料庫讀取的其他類,但是,所有的代碼都引用從檔案讀取的原始類。這時候,使用原廠模式會很方便。
原廠模式是一種類,它具有為您建立對象的某些方法。您可以使用工廠類建立對象,而不直接使用 new。這樣,如果您想要更改所建立的物件類型,只需更改該工廠即可。使用該工廠的所有代碼會自動更改。
樣本1:顯示工廠類的一個示列。等式的伺服器端包括兩個部分:資料庫和一組 PHP 頁面,這些頁面允許您添加反饋、請求反饋列表並擷取與特定反饋相關的文章。
interface IUser { function getName(); } class User implements IUser { public function __construct( $id ) { } public function getName() { return "Jack"; } } class UserFactory { public static function Create( $id ) { return new User( $id ); } } $uo = UserFactory::Create( 1 ); echo( $uo->getName()."\n" ); ?>
IUser介面定義使用者物件應執行什麼操作。IUser 的實現稱為 User,UserFactory 工廠類則建立 IUser 對象。此關係可以用圖1中的UML 表示。
圖 1. 工廠類及其相關 IUser 介面和使用者類
如果您使用 php 解譯器在命令列上運行此代碼,將得到如下結果:
% php factory1.php Jack %
測試代碼會向工廠請求 User 對象,並輸出 getName 方法的結果。
有一種原廠模式的變體使用Factory 方法。類中的這些公用靜態方法構造該類型的對象。如果建立此類型的對象非常重要,此方法非常有用。例如,假設您需要先建立對象,然後設定許多屬性。此版本的原廠模式會將該進程封裝在單個位置中,這樣,不用複製複雜的初始化代碼,也不必將複製好的代碼在在程式碼程式庫中到處粘貼。
樣本2 顯示使用Factory 方法的一個樣本。
interface IUser { function getName(); } class User implements IUser { public static function Load( $id ) { return new User( $id ); } public static function Create( ) { return new User( null ); } public function __construct( $id ) { } public function getName() { return "Jack"; } } $uo = User::Load( 1 ); echo( $uo->getName()."\n" ); ?>
這段代碼要簡單得多。它僅有一個介面 IUser 和一個實現此介面的 User 類。User 類有兩個建立對象的靜態方法。此關係可用圖 2 中的 UML 表示。
圖 2. IUser 介面和帶有Factory 方法的 user 類
在命令列中運行指令碼產生的結果與清單 1 的結果相同,如下所示:
% php factory2.php Jack %
如上所述,有時此類模式在規模較小的環境中似乎有些大材小用。不過,最好還是學習這種紮實的編碼形式,以便應用於任意規模的項目中。