PHP三層結構(上) 簡單三層結構
// 代碼 1
// 外觀層類
class LWordHomePage {
// 添加留言
public function append($newLWord) {
// 調(diào)用中間服務層
$serv = new LWordServiceCore();
$serv->append($newLWord);
}
};
// 中間服務層
class LWordServiceCore {
// 添加留言
public function append($newLWord) {
// 調(diào)用數(shù)據(jù)訪問層
$dbTask = new LWordDBTask();
$dbTask->append($newLWord);
}
};
// 數(shù)據(jù)訪問層
class LWordDBTask {
// 添加留言
public function append($newLWord) {
// 數(shù)據(jù)層代碼(省略)
}
};
執(zhí)行時序圖,如圖1所示:

(圖1),簡單三層結構時序圖
從代碼和時序圖中可以直觀看出三層結構的調(diào)用順序。但實際開發(fā)中這種簡單三層結構并不能滿足需求!我們先從外觀層與中間服務層這兩層的代碼開始討論。在外觀層LWordHomePage類中直接使用new關鍵字創(chuàng)建并調(diào)用中間服務類LWordServiceCore屬于一種硬編碼的方式。在實際項目開發(fā)過程中,外觀層和中間服務層可能會由不同的人員來開發(fā),即一個功能模塊由多個人共同完成。而外觀層LWordHomePage類的開發(fā)進度是不可能等到LWordServiceCore類完全開發(fā)完成之后才開始(換句話來說就是,外觀層不可能等到中間服務層完全開發(fā)完成之后才開始),這樣的協(xié)作效率非常低!為了使項目可以由多人同時開發(fā),所以我們要切割代碼設計。我們可以組織一個臨時的中間服務類來滿足外觀層的開發(fā)進度。等到中間服務層完全開發(fā)完成之后,替換一下就可以了……如圖2所示:
(圖2),外觀層在不同的服務間切換
顯然,要實現(xiàn)這樣的需求,在外觀層中直接使用new關鍵字創(chuàng)建和調(diào)用LWordServiceCore類是非常不靈活的!這很難做到靈活的隨意的切換?。∥覀兛梢詣?chuàng)建TempService類充當中間服務層的臨時實現(xiàn)。我們還需要分析一下TempService和LWordServiceCore這兩個類,它們都具備相同的append函數(shù)用于添加留言,只不過一個是臨時的而另外一個是真實的。既然TempService和LWordServiceCore這兩個類都有公共函數(shù),那么就應該可以有一個公共的父類??紤]到對這個公共的上級類沒有別的成員和屬性,所以將這個公共的上級類定義為接口,即ILWordService!UML類圖如圖3所示:

(圖3)定義和實現(xiàn)ILWordService接口
在LWordHomePage類中并不直接創(chuàng)建TempService或者LWordServiceCore類對象,創(chuàng)建過程會交給一個工廠類MyServiceFactory(簡單工廠模式)。這樣一來,外觀層中的LWordHomePage類只需要知道ILWordService接口即可,外觀層代碼并不關心具體的中間服務代碼是什么,這樣就極好的實現(xiàn)了外觀層與具體服務代碼的分離。
這相當于什么呢?就好比兩個硬件工程師,一個是制造計算機顯卡的,一個是制造計算機主板的。制造顯卡的工程師可以把顯卡插到到一塊測試電路中,來測試顯卡是否可以正常工作?同樣,制造主板的工程師也可以把主板插入到另一塊測試電路中,來測試主板是否可以正常工作?等到這兩位工程師都各自完成工作之后,將他倆的工作成果對接在一起就可以了。這是一種并行開發(fā)方式,幾乎可以省掉一半的時間。從軟件工程的角度來講,我們在設計接口代碼的時候也應該考慮是否需要支持多人同時開發(fā),從而提高生產(chǎn)效率。
依照UML類圖(如圖3所示),我們修改PHP代碼如代碼2所示:
// 代碼2, 通過工廠創(chuàng)建留言服務并調(diào)用
// 外觀層類
class LWordHomePage {
// 添加留言
public function append($newLWord) {
// 調(diào)用中間服務
$serv = MyServiceFactory::create();
// 注意此時是操作 ILWordService 接口, 而非 LWordService 類
$serv->append($newLWord);
}
};
// 留言服務接口
interface ILWordService {
public function append($newLWord);
};
// 服務工廠類
class MyServiceFactory {
// 創(chuàng)建留言服務
public static function create() {
if (1) {
// 返回中間服務層
return new LWordServiceCore();
} else {
// 返回臨時實現(xiàn)
return new TempService();
}
}
}
// 臨時服務類
class TempService implements ILWordService {
// 添加留言
public function append($newLWord) {
// 臨時代碼(省略)
}
};
// 中間服務層
class LWordServiceCore implements ILWordService {
// 添加留言
public function append($newLWord) {
// 調(diào)用數(shù)據(jù)訪問層
$dbTask = new LWordDBTask();
$dbTask->append($newLWord);
}
};
// 數(shù)據(jù)訪問層
class LWordDBTask {
// 添加留言
public function append($newLWord) {
// 數(shù)據(jù)層代碼(省略)
}
};
時序圖如圖4所示:

(圖4)通過工廠類創(chuàng)建留言服務
相關文章
php heredoc和phpwind的模板技術使用方法小結
Heredoc技術,在正規(guī)的PHP文檔中和技術書籍中一般沒有詳細講述,只是提到了這是一種Perl風格的字符串輸出技術。但是現(xiàn)在的一些論壇程序,和部分文章系統(tǒng),都巧妙的使用heredoc技術,來部分的實現(xiàn)了界面與代碼的準分離,phpwind就是一個典型的例子。2008-03-03
解析如何通過PHP函數(shù)獲取當前運行的環(huán)境 來進行判斷執(zhí)行邏輯(小技巧)
本篇文章是對如何通過PHP函數(shù)獲取當前運行的環(huán)境 來進行判斷執(zhí)行邏輯的技巧進行了詳細的分析介紹,需要的朋友參考下2013-06-06
如何讓thinkphp在模型中自動完成session賦值小教程
在項目中遇到一個問題,需要讓thinkphp在模型中自動完成session賦值,經(jīng)過一番研究,終于實現(xiàn),下面記錄一下,另附上thinkPHP的session的相關知識2014-09-09
PHP 數(shù)組遍歷方法大全(foreach,list,each)
php下最靈活的東西都是數(shù)組,很多數(shù)據(jù)都是通過數(shù)組的方式顯示,這里整理下數(shù)組的遍歷方法,大家可以根據(jù)需要選用。2010-06-06

