《設計模式》中對Facade模式是這樣敘述的:
為子系統的一組介面提供一個統一介面。Facade模式定義了一個更高層的介面,使得子系統更加容易使用。
Facade模式的關鍵特徵:
意圖:希望簡化原有系統的使用方式,需要定義自己的介面。問題:只需要使用某個複雜系統的子集,或則,需要一種一種特殊的方式與系統互動。解決方案:為原有系統的客戶提供了一個統一的高層的介面。參與者與共同作業者:介面本身和各個子系統。效果:簡化了對子系統的使用過程。實現:定義一個具備所需介面的新類。讓新的類使用原有的系統。
展示了Facade模式的作用。
這就是Facade模式。通過這個模式我們能夠更加容易地使用一個複雜的系統。另外,Facade模式不僅可以建立更加簡單的介面,還能夠用來減少用戶端使用者必須處理的對象數量,或者用來隱藏封裝系統。
下面以代碼為例。其功能只是沖檔案中擷取log資訊並把它轉換為對象資料:
function getProductFileLines($file){ return file($file);}function getProductObjectFromId($id,$productName){ return new Product($id,$productName);}function getNameFromLine($line){ if(preg_match("/.*-(.*)\s\d+/",$line,$array)){ return str_replace('_',' ',$array[1]); } return '';}function getIdFromLine($line){ if(preg_match("/^(\d{1,3})/",$line,$array)){ return $array[1]; } return '';}class Product{ private $id; private $name; public function __construct($id,$name){ $this->id = $id; $this->name = $name; } }
這組介面的作用是把類似:234-ladies_jumper 55 這樣的資料轉化為一個對象數組。如果使用的話,必須調用所有這些方法:
$lines = getProductFileLines('test.txt');$objects = array();foreach( $lines as $line ){ $id = getIDFromLine($line); $name = getNameFromLine($line); $objects[$id] = getProductObjectFromId($id,$name);}
這顯然是緊耦合的表現。且每次調用這麼多的介面無疑讓人很頭疼。
下面的代碼展示了使用Facade模式的解決方案。
class ProductFacade{ private $products = array(); private $file = ''; public function __construct($file){ $this->file = $file; $this->compile(); } private function compile(){ $id = getIDFromLine($line); $name = getNameFromLine($line); $this->products[$id] = getProductObjectFromId( $id,$name ); } public function getProducts(){ return $this->products; } public function getProduct($id){ return $this->products[$id]; }}
現在,可以很方便地很簡單地訪問Product對象:
$facade = new ProductFacade('test.txt');print $facade->getProduct(234);
總結之:Facade模式為一個分層或者一個子系統建立了一個單一的入口。這樣做的好處有:
1.有助於分離項目中的不同部分。2.對於用戶端開發人員來說,存取碼更加簡潔,非常方便3.由於只在一個地方調用子系統,減少了出錯的可能性4.還能避免用戶端代碼不正確滴使用子系統中複雜的內部方法,從而減少錯誤的發生。5.封裝或者隱藏原系統。