PHP三層結構(下) PHP實現AOP第1/2頁

來源:互聯網
上載者:User

本文源碼:http://xiazai.jb51.net/201007/yuanma/TraceLWord.rar
開發環境為 eclipse(pdt)
讓我們把注意力集中到中間服務層上來。中間服務層代碼比較簡單,只是調用資料訪問層代碼將留言儲存到資料庫。如代碼1所示: 複製代碼 代碼如下:// 代碼 1
// 中間服務層
class LWordServiceCore implements ILWordService {
// 添加留言
public function append($newLWord) {
// 調用資料訪問層
$dbTask = new LWordDBTask();
$dbTask->append($newLWord);
}
};

在看到留言板的示範之後,公司的產品部和市場部或許會提出各種各樣的想法和需求。比如他們希望在添加留言之前判斷使用者的許可權!只有註冊使用者才能留言!我們需要修改代碼,如代碼2所示: 複製代碼 代碼如下:// 代碼 2, 增加登入驗證
// 中間服務層
class LWordServiceCore implements ILWordService {
// 添加留言
public function append($newLWord) {
if (!($userLogin)) {
// 提示使用者登入
}
// 調用資料訪問層
$dbTask = new LWordDBTask();
$dbTask->append($newLWord);
}
};

市場部又希望在添加留言之前,對留言內容進行檢查,如果留言中含有髒話就不儲存。我們繼續修改代碼,如代碼3所示: 複製代碼 代碼如下:// 代碼 3, 增加髒話過濾
// 中間服務層
class LWordServiceCore implements ILWordService {
// 添加留言
public function append($newLWord) {
if (!($userLogin)) {
// 提示使用者登入
}
if (stristr($newLWord, "SB")) {
// 含有髒話, 提示留言發送失敗
}
// 調用資料訪問層
$dbTask = new LWordDBTask();
$dbTask->append($newLWord);
}
};

產品部也提出了新需求,他們希望加入積分機制。具體來講就是在使用者每次留言成功以後給使用者+5分。我們繼續修改代碼,如代碼4所示: 複製代碼 代碼如下:// 代碼 4, 加入留言積分機制
// 中間服務層
class LWordServiceCore implements ILWordService {
// 添加留言
public function append($newLWord) {
if (!($userLogin)) {
// 提示使用者登入
}
if (stristr($newLWord, "SB")) {
// 含有髒話, 提示留言發送失敗
}
// 調用資料訪問層
$dbTask = new LWordDBTask();
$dbTask->append($newLWord);
// 給使用者加分
$score = getUserScore($userName);
$score = $score + 5;
saveUserScore($userName, $score);
}
};

沒過多久,產品部又對需求進行細化,他們希望使用者積分每積累夠1000分以後,就給使用者升級。我們繼續修改代碼,如代碼5所示: 複製代碼 代碼如下:// 代碼 5, 加入使用者升級規則
// 中間服務層
class LWordServiceCore implements ILWordService {
// 添加留言
public function append($newLWord) {
if (!($userLogin)) {
// 提示使用者登入
}
if (stristr($newLWord, "fuck")) {
// 含有髒話, 提示留言發送失敗
}

// 調用資料訪問層
$dbTask = new LWordDBTask();
$dbTask->append($newLWord);
// 給使用者加分
$score = getUserScore($userName);
$score = $score + 5;
saveUserScore($userName, $score);
// 給使用者升級
if (($score % 1000) == 0) {
$level = getUserLevel($userName);
$level = $level + 1;
saveUserLevel($userName, $level);
}
}
};

隨著需求的增多,我們需要不斷的修改中間服務層代碼。但是你應該不難發現,需求越多中間服務層代碼也就越多越龐大!最後會導致即便我們使用三層結構的開發模式,也還是沒有有效降低工程難度!另外就是應需求的變化而修改中間服務代碼以後,需要重新測試所有代碼,而不是有效測試新增代碼……

其實讓我們仔細分析一下這個留言板代碼,我先要提出一個主商務邏輯和次商務邏輯的概念。無論怎樣,把留言內容存入到資料庫,這是商務邏輯的主幹!這個就是主商務邏輯!這部分沒有隨著需求的增加而修改。至於在存入資料庫之前要進行許可權校正,要進行內容檢查,存入資料庫之後要給使用者加分,然後給使用者升級,這些都是前序工作和掃尾工作,都是次商務邏輯!主商務邏輯幾乎是一成不變的,次商務邏輯變化卻非常頻繁。為了提高代碼的可讀性和可維護性,我們可以考慮把這些次商務邏輯放到別的地方,盡量不要讓它們幹擾主商務邏輯。主商務邏輯專心幹自己該乾的事情好了,至於別的任何事情,主商務邏輯一概都不聞不問!那麼我們的代碼就可以寫成這樣,如代碼6所示: 複製代碼 代碼如下:// 代碼 6, 將主商務邏輯和次商務邏輯分開
// 中間服務層
class LWordServiceCore implements ILWordService {
// 添加留言
public function append($newLWord) {
// 添加留言前
beforeAppend($newLWord);
// 調用資料訪問層
$dbTask = new LWordDBTask();
$dbTask->append($newLWord);
// 添加留言後
behindAppend($newLWord);
}
};

我們可以把許可權判斷代碼和留言內容文本過濾代碼統統塞進beforeAppend函數,把使用者積分代碼塞進behindAppend函數,這樣就把次商務邏輯從主商務邏輯代碼中清理掉了。主商務邏輯知道有個“序曲”函數beforeAppend,有個“尾聲”函數behindAppend,但是在序曲和尾聲函數中具體都做了什麼事情,主商務邏輯並不知道,也不需要知道!當然實際編碼工作並不那麼簡單,我們還要兼顧產品部和市場部更多的需求變化,所以最好能實現一種外掛程式方式來應對這種變化,但是僅僅依靠兩個函數beforeAppend和behindAppend是達不到這個目的~

想要實現外掛程式方式,可以建立介面!使用介面的好處是可以將定義和實現隔離,另外就是實現多態。我們建立一個留言擴充介面ILWordExtension,該介面有兩個函數beforeAppend和behindAppend。許可權校正、內容檢查、加分這些功能可以看作是實現ILWordExtension介面的三個實作類別,主商務邏輯就依次遍曆這三個實作類別,來完成次商務邏輯。1所示:
CheckPowerExtension擴充類用作使用者權限校正,CheckContentExtension擴充類用作留言內容檢查,AddScoreExtension擴充類用作給使用者加分和升級。示意代碼如代碼7所示:

(圖1),加入擴充介面複製代碼 代碼如下:// 代碼 7,加入擴充介面
// 擴充介面
interface ILWordExtension {
// 添加留言前
public function beforeAppend($newLWord);
// 添加留言後
public function behindAppend($newLWord);
};

// 檢查許可權
class CheckPowerExtension implements ILWordExtension {
// 添加留言前
public function beforeAppend($newLWord) {
// 在這裡判斷使用者權限
}

// 添加留言後
public function behindAppend($newLWord) {
}
};

// 檢查留言文本
class CheckContentExtension implements ILWordExtension {
// 添加留言前
public function beforeAppend($newLWord) {
if (stristr($newLWord, "SB")) {
throw new Exception();
}
}

// 添加留言後
public function behindAppend($newLWord) {
}
};

// 使用者積分
class AddScoreExtension implements ILWordExtension {
// 添加留言前
public function beforeAppend($newLWord) {
}

// 添加留言後
public function behindAppend($newLWord) {
// 在這裡給使用者積分
}
};

// 中間服務層
class LWordServiceCore implements ILWordService {
// 添加留言
public function append($newLWord) {
// 添加留言前
$this->beforeAppend($newLWord);

// 調用資料訪問層
$dbTask = new LWordDBTask();
$dbTask->append($newLWord);

// 添加留言後
$this->behindAppend($newLWord);
}

// 添加留言前
private function beforeAppend($newLWord) {
// 擷取擴充數組
$extArray = $this->getExtArray();

foreach ($extArray as $ext) {
// 遍曆每一個擴充, 並調用其 beforeAppend 函數
$ext->beforeAppend($newLWord);
}
}

// 添加留言後
private function behindAppend($newLWord) {
// 擷取擴充數組
$extArray = $this->getExtArray();

foreach ($extArray as $ext) {
// 遍曆每一個擴充, 並調用其 behindAppend 函數
$ext->behindAppend($newLWord);
}
}

// 擷取擴充數組,
// 該函數的傳回值實際上是 ILWordExtension 介面數組
private function getExtArray() {
return array(
// 檢查許可權
new CheckPowerExtension(),
// 檢查內容
new CheckContentExtension(),
// 加分
new AddScoreExtension(),
);
}
};

如果還有新需求,,我們只要再添加ILWordExtension 實作類別並且把它註冊到getExtArray函數裡即可。程式從此有了條理,並且算是具備了可擴充性。

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.