php設(shè)計模式介紹之編程慣用法第2/3頁
更新時間:2008年04月13日 22:07:20 作者:
《PHP設(shè)計模式介紹》第一章 編程慣用法
學(xué)習(xí)一門新的語言意味著要采用新的慣用法。這章將介紹或者可能重新強調(diào)一些慣用法。你會發(fā)現(xiàn)這些慣用法在你要在代碼中實現(xiàn)設(shè)計模式時候是非常有用的。
重構(gòu)
即使最有思想性且最熟練的程序員也不能預(yù)見一個軟件項目中的任何細(xì)微之處。問題總是出乎意外的出現(xiàn),需求也可能在變化,結(jié)果是代碼被優(yōu)化,共享然后代替。
重構(gòu)是一個慣用的方法:檢查你所有的代碼,找出其中能統(tǒng)一化和簡單化的共同或者類似之處,使得你的代碼更加容易維護和擴展。重構(gòu)也包括探索一個設(shè)計模式是否能夠應(yīng)用到這個具體的問題上——這也能使解決方案簡單化。
重構(gòu),簡單點說是重命名一個屬性或者方法,復(fù)雜點說是壓縮一個已有的類。改變你的代碼使得它符合一個或者更多的設(shè)計模式是另外一種重構(gòu)——讀完這本書后,你可能會去實現(xiàn)的。
沒有什么能比例子來更好的解釋重構(gòu)了!
讓我們考慮兩個簡單的類:CartLine和Cart。CartLine記錄了購物車?yán)锩婷總€項目的單件價格和數(shù)量。比如CartLine可能記錄著“四見紅色的polo襯衣,每件19.99$”。Cart 是一個容器,用來裝載一個或者更多的CartLine對象并執(zhí)行一些相關(guān)的計算工作,比如購物車?yán)锩娴乃猩唐返目偦ㄙM。
下面是CartLine和Cart的簡單實現(xiàn):
// PHP5
class CartLine {
public $price = 0;
public $qty = 0;
}
class Cart {
protected $lines = array();
public function addLine($line) {
$this->lines[] = $line;
}
public function calcTotal() {
$total = 0;
// add totals for each line
foreach($this->lines as $line) {
$total += $line->price * $line->qty;
}
// add sales tax
$total *= 1.07;
return $total;
}
}
重構(gòu)的第一步必須有足夠的測試來覆蓋你所有的代碼。這樣才能保證你修改的代碼不能產(chǎn)生和你原來代碼不同的結(jié)果。順便提一下,除非你改變了需求(你代碼期望的結(jié)果)或者在測試實例中發(fā)現(xiàn)了錯誤,你的測試代碼是是不能改變的。
下面是一個測試CartLine和Cart的例子,它在重構(gòu)的過程中是不會改變的。
function TestCart() {
$line1 = new CartLine;
$line1->price = 12; $line1->qty = 2;
$line2 = new CartLine;
$line2->price = 7.5; $line2->qty = 3;
$line3 = new CartLine;
$line3->price = 8.25; $line3->qty = 1;
$cart = new Cart;
$cart->addLine($line1);
$cart->addLine($line2);
$cart->addLine($line3);
$this->assertEqual(
(12*2 + 7.5*3 + 8.25) * 1.07,
$cart->calcTotal());
}
看著上面的代碼,你可能會發(fā)現(xiàn)它們有一些“code smells”(代碼臭味)——有著古怪的樣子而且看起來好像是有問題的代碼——它們就像重構(gòu)的候選項。(更多關(guān)于code smells的資料請看http://c2.com/cgi/wiki?codesmell)。兩個最直接的重構(gòu)候選者是注釋和計算(與銷售稅等相關(guān)的計算)。重構(gòu)的一種形式:析取函數(shù)(Extract Method)將把這些難看的代碼從cart::calcTotal()中提取出來,然后用一個合適的方法來替代它,從而使得代碼更加簡潔。
比如,你可以增加兩個計算方法:lineTotal()和calcSalesTax():
protected function lineTotal($line) {
return $line->price * $line->qty;
}
protected function calcSalesTax($amount) {
return $amount * 0.07;
}
現(xiàn)在你可以重寫calcTotal()函數(shù):
public function calcTotal() {
$total = 0;
foreach($this->lines as $line) {
$total += $this->lineTotal($line);
}
$total += $this->calcSalesTax($total);
return $total;
}
到目前為止的改動都是有意義的(至少在這個例子的上下文中),它對于再次暫停和運行這些代碼來驗證結(jié)果依然正確是很有幫助的。記得,一個綠色的成功條的顯示出來了?。ㄗg者注:本章開始時,作者提及到:綠色的條意味著測試都通過了。)
然而,目前的代碼依然有一些可以挑剔的地方。其中一個就是在新方法lineTotal()中存取公共屬性。很明顯計算每行的之和的責(zé)任不應(yīng)該屬于Cart類,而應(yīng)該在類CartLine里面實現(xiàn)。
再次重構(gòu),在CartLine中增加一個新的方法total()用來計算訂單里面的每個項目的長期價錢。
public function total() {
return $this->price * $this->qty;
}
然后從類Cart中移除方法lineTotal(),并改變calcTotal()方法來使用新的cartLine::Total()方法。重新運行這個測試,你依然會發(fā)現(xiàn)結(jié)果是綠色條。
全新重構(gòu)后的代碼就是這樣:
class CartLine {
public $price = 0;
public $qty = 0;
public function total() {
return $this->price * $this->qty;
}
}
class Cart {
protected $lines = array();
public function addLine($line) {
$this->lines[] = $line;
}
public function calcTotal() {
$total = 0;
foreach($this->lines as $line) {
$total += $line->total();
}
$total += $this->calcSalesTax($total);
return $total;
}
protected function calcSalesTax($amount) {
return $amount * 0.07;
}
}
現(xiàn)在這代碼不再需要每行注釋了,因為代碼本身更好的說明了每行的功能。這些新的方法,更好的封裝了計算這個功能,也更加容易適應(yīng)將來的變化。(比如說,考慮不同大的銷售稅率)。另外,這些類也更加平衡,更容易維護。
這個例子顯然是微不足道的,但是希望你能從中推斷并預(yù)想出如何重構(gòu)你自己的代碼。
在編碼的時候,你應(yīng)該有出于兩種模式中的一種:增加新的特征或者重構(gòu)代碼。當(dāng)在增加特征的時候,你要寫測試和增加代碼。在重構(gòu)的時候,你要改變你原有的代碼,并確保所有相關(guān)的測試依然能正確運行。
關(guān)于重構(gòu)的主要參考資料有Martin Fowler著作的《重構(gòu):改進原有代碼的設(shè)計》(Refactoring:Improving the Design of Existing Code)。用一些精簡點來總結(jié)Fowler的書,重構(gòu)的步驟如下所示:
定義需要重構(gòu)的代碼
有覆蓋所有代碼的測試
小步驟的工作
每步之后都運行你的測試。編碼和測試都是相當(dāng)重復(fù)的——和編譯型語言相比,解釋型語言,比如PHP是容易很多的。
使用重構(gòu)來使你的代碼有更好的可讀性和可修改性。
您可能感興趣的文章:
- php設(shè)計模式 Observer(觀察者模式)
- php設(shè)計模式 Singleton(單例模式)
- php設(shè)計模式 Command(命令模式)
- php設(shè)計模式 Composite (組合模式)
- php設(shè)計模式 Bridge (橋接模式)
- php設(shè)計模式 Chain Of Responsibility (職責(zé)鏈模式)
- php設(shè)計模式 Mediator (中介者模式)
- php設(shè)計模式 Prototype (原型模式)代碼
- php設(shè)計模式 Command(命令模式)
- 介紹php設(shè)計模式中的工廠模式
- php設(shè)計模式介紹之值對象模式
- php設(shè)計模式 Strategy(策略模式)
- php設(shè)計模式 FlyWeight (享元模式)
- php設(shè)計模式 State (狀態(tài)模式)
- php設(shè)計模式 Proxy (代理模式)
- php設(shè)計模式 Template (模板模式)
相關(guān)文章
echo(),print(),print_r()之間的區(qū)別?
echo(),print(),print_r()之間的區(qū)別?...2006-11-11PHP靜態(tài)方法和靜態(tài)屬性及常量屬性的區(qū)別與介紹
今天小編就為大家分享一篇關(guān)于PHP靜態(tài)方法和靜態(tài)屬性及常量屬性的區(qū)別與介紹,小編覺得內(nèi)容挺不錯的,現(xiàn)在分享給大家,具有很好的參考價值,需要的朋友一起跟隨小編來看看吧2019-03-03PHP保存session到memcache服務(wù)器的方法
這篇文章主要介紹了PHP保存session到memcache服務(wù)器的方法,涉及PHP操作session及memcache的相關(guān)技巧,需要的朋友可以參考下2016-01-01php連接mysql數(shù)據(jù)庫最簡單的實現(xiàn)方法
在本篇文章里小編給大家分享的是關(guān)于php怎樣連接mysql數(shù)據(jù)庫的相關(guān)實例內(nèi)容,有需要的朋友們參考下。2019-09-09