php設計模式介紹之偽對象模式

來源:互聯網
上載者:User

物件導向的編程之所以豐富多彩,部分是由於對象間的相互聯絡與作用。一個單一的對象就能封裝一 個複雜的子系統,使那些很複雜的操作能夠通過一些方法的調用而簡化。(無所不在的資料庫連接就是 這樣的一個對象執行個體。)

然而經常有這樣的情況,對象間的互動性是如此複雜以至於我們不得 不面對類似“先有雞還是先有蛋”這樣傷腦筋的問題:如何建立並測試這樣一個對象,他要 麼依賴於很多已建立的對象,要麼依賴於其他一些難以意識到的情況,如整個資料庫的建立和測試。

問題

如何分隔並測試一個與其他對象和資源有關的程式碼片段?又如何再建立一個或多個對 象、程式來驗證你的代碼能正常運行?

解決方案

當用situ(或在一個模擬的程式環境 中)測試一個對象代價不菲或困難重重時,就可用偽對象來類比這個行為。偽對象有同真實對象一樣的 介面,但卻能提供先行編譯響應,能跟蹤方法調用,並驗證調用次序。

偽對象是測試的“特 別力量”。他們被秘密訓練,滲透進目標代碼,類比並監視通訊方式,回報結果。偽對象有助於查 找和消除程式漏洞並能支援更多正常調試環境下的“防危險”操作。

註:The ServerStub

偽對象模式是另一種測試模式ServerStub的擴充。ServerStub模式替代一個資源並返 回其方法所調用的相應值。當其參與指定次序的方法的調用時ServerStub就成了偽對象。

其並非 是一個設計模式

本章與其他章不同,因為偽對象是一個測試模式而不是設計模式。這類似於一 個附加的章節,但對它的使用確實很值得你納入到編碼進程中。另一個不同是我們不再關注這個模式如 何編碼之類的基礎問題,而是強調如何在SimpleTest中使用偽對象。

本章先舉一個非常簡單的例 子來示範SimpleTest下偽對象的基本機制。然後向你示範如何使用偽對象協助重構已有代碼與如何測試 新的解決方案。

樣本代碼

偽對象是對象在測試中的一個替代品,用它測試代碼更加簡便 。例如,替代一個真實的資料連線——這個真實的資料連線由於一些原因而不能實際串連 ——你就可以建立一個偽對象來類比。這意味著偽對象需要準確地回應代碼中所調用的相同 的應用程式介面。

讓我們建立一個偽對象來替代一個簡單的名為Accumulator的類,這是一個求 和的類。如下是最初的Accumulator類:

// PHP4

class Accumulator {
var $total=0;
function add($item) {
$this->total += $item;
}
function total() {
return $this->total;
}
}

這個類中add()函數先累加值 到$total變數中,再交由total()函數返回 。 一個簡單的累加也可以如下面這樣(下面的代碼被編寫為 一個函數,但它也可以寫成一個類)。

function calc_total($items, &$sum) {
foreach($items as $item) {
$sum->add($item);
}
}
function calc_tax(&$amount, $rate=0.07) {
return round($amount->total() * $rate,2);
}

第一個函數calc_total()用一個累加的動作求一系列值的和。下面是簡單的測試:

class MockObjectTestCase extends UnitTestCase {
function testCalcTotal() {
$sum =& new Accumulator;
calc_total(array(1,2,3), $sum);
$this- >assertEqual(6, $sum->total());
}
}

讓我們關注第二個例子。假設 實現一個真實的累加動作的代價很大。那麼用一個簡單的對象來替代它並回應相關代碼就是很好的做法 了。使用SimpleTest,你可以用如下代碼建立一個偽累加動作:

為了使用偽對象,具有代表性 的做法是你親自寫一個新類(並不要求馬上做)。幸運的是,SimpleTest有一種容易的手段來實現 Mock::generate() 方法。

在上面的例子中,這種手段建立了一個名為MockAccumulator的類來響 應所有Accumulator類的方法。另外,偽累加的動作還有其他手段來操作偽對象自身的執行個體。例如 setReturnValue()。給出一個方法名和一個值,

setReturnValue()就可以改變偽對象而給出對應 方法所調用的值。因此,這條語句$amount->setReturnValue(‘total’, 200)返回200而 不論何時調用了total()方法。

一旦進行完初始化工作後,你可以傳遞MockAccumulator類到 calc_tax()函數來示範一個在真實的Accumulator對象空間中的動作。

如果你止步於此 ——即用一個對象來返回所調用函數的“封裝”響應——你只是使用 了ServerStub模式。 用偽對象來驗證方法的調用不限於此,因為它可以不限次序與次數。

下面 是一個通過對象來驗證“資料流”的例子:

class MockObjectTestCase extends UnitTestCase {
// ...
function testCalcTax() {
$amount =& new MockAccumulator($this);
$amount->setReturnValue(‘total’,200);
$amount->expectOnce(‘total’);
$this->assertEqual(
14, calc_tax($amount));
$amount->tally();
}
}

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在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.