外觀(Facade)模式 當使用子系統的代碼時,你也許會發現自己過於深入地調用子系統的邏輯代碼。如果子系統代碼總是在不斷變化,而你的代碼卻又在許多不同地方與子系統代碼交互,那麼隨著子系統的發展,你也許會發現維護代碼變得非常困難。 在項目中集成複雜的第三方代碼,或在系統中逐漸形成大量僅在系統自身內部有 ...
外觀(Facade)模式
當使用子系統的代碼時,你也許會發現自己過於深入地調用子系統的邏輯代碼。如果子系統代碼總是在不斷變化,而你的代碼卻又在許多不同地方與子系統代碼交互,那麼隨著子系統的發展,你也許會發現維護代碼變得非常困難。
在項目中集成複雜的第三方代碼,或在系統中逐漸形成大量僅在系統自身內部有用的代碼,在這些情況下,你總可以應用外觀模式,為複雜的系統創建一個簡單、清晰的介面。
假設有下麵一段很亂的代碼,其功能是從文件中獲取log信息並將它轉換為對象:
function getProductFileLines($file)
{
return file($file);
}
function getProductObjectFromID($id, $productname)
{
// 一些資料庫查詢
return new Product($id, $productname);
}
function getNameFromLine()
{
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 -1;
}
class Product()
{
public $id;
public $name;
public __construct($id, $name)
{
$this->id = $id;
$this->id = $name;
}
}
我們的目的是將包含類似下麵數據的文件轉換為一個對象數組:
234-ladies_jumper 55
532-gents_hat 44
客戶端使用該功能時要調用所有的方法:
$lines = getProductFileLines('text.txt');
$objects = array();
foreach ($lines as $line) {
$id = getIDFromLine($line);
$name = getNameFromLine($line);
$objects[$id] = getProductObjectFromID($id, $name);
}
如果在項目中直接調用這些方法,那麼我們的代碼會和子系統緊緊耦合在一起。當子系統變化時,或者我們決定將其與子系統完全斷開時,代碼就會出問題。
下麵這個簡單的類為上面的過程式代碼提供了一個介面:
class ProductFacade
{
private $products = array();
function __construct($file)
{
$this->file = $file;
$this->compile();
}
private function complie()
{
$lines = getProductFileLines($this->line);
foreach ($lines as $line) {
$id = getIDFromLine($line);
$name = getNameFromLine($line);
$this->products[$id] = getProductObjectFromID($id, $name);
}
}
function getProducts()
{
return $this->products;
}
function getProduct($id)
{
return $this->product[$id];
}
}
現在,從一個log文件訪問Product對象就簡單多了:
$facade = new ProductFacade('test.txt');
$facade->getProduct(234);
外觀模式的好處:(1)對於調用者來說,訪問代碼變得簡潔、非常方便.(2),由於只在一個地方調用子系統,減少了出錯的可能.(3),Facade類還能使調用者避免不正確地使用內部方法,從而減少錯誤的發生。
註1:這是《深入PHP:面對對象、模式與實踐》第十章的部分內容(其他的都看不懂,逃~)
註2:此文章也可以在我單獨的博客裡面看到: https://feiffy.cc/%E3%80%8A%E6%B7%B1%E5%85%A5PHP%EF%BC%9A%E9%9D%A2%E5%AF%B9%E5%AF%B9%E8%B1%A1%E3%80%81%E6%A8%A1%E5%BC%8F%E4%B8%8E%E5%AE%9E%E8%B7%B5%E3%80%8B#.E5.A4.96.E8.A7.82.28Facade.29.E6.A8.A1.E5.BC.8F