欧美三区_成人在线免费观看视频_欧美极品少妇xxxxⅹ免费视频_a级毛片免费播放_鲁一鲁中文字幕久久_亚洲一级特黄

另外五個(gè) PHP 設(shè)計(jì)模式

系統(tǒng) 3008 0

另外五個(gè) PHP 設(shè)計(jì)模式

級別: 中級

Nathan A. Good ( mail@nathanagood.com ), 高級信息工程師, 顧問

2008 年 4 月 28 日

PHP V5 的面向?qū)ο筇匦允鼓軌驅(qū)崿F(xiàn)設(shè)計(jì)模式來改進(jìn)代碼設(shè)計(jì)。通過這種方式改進(jìn)代碼設(shè)計(jì),代碼在進(jìn)行修改時(shí)將變得更加易讀、更易維護(hù)且更加健壯。
<!--START RESERVED FOR FUTURE USE INCLUDE FILES--><!-- include java script once we verify teams wants to use this and it will work on dbcs and cyrillic characters --><!--END RESERVED FOR FUTURE USE INCLUDE FILES-->

設(shè)計(jì)模式 一書介紹了很多此類概念。當(dāng)時(shí),我還在學(xué)習(xí)面向?qū)ο?(OO),因此我發(fā)現(xiàn)那本書中有許多概念都很難領(lǐng)會(huì)。但是,隨著越來越熟悉 OO 概念 —— 尤其是接口和繼承的使用 —— 我開始看到設(shè)計(jì)模式中的實(shí)際價(jià)值。作為一名應(yīng)用程序開發(fā)人員,即使從不了解任何模式或者如何及何時(shí)使用這些模式,對您的職業(yè)生涯也沒有什么大的影響。但是,我發(fā)現(xiàn)了解這些模式以及 developerWorks 文章 “五種常見 PHP 設(shè)計(jì)模式” 中介紹的那些模式的優(yōu)秀知識后(請參閱 參考資料 ),您可以完成兩件事情:

啟用高帶寬會(huì)話
如果了解設(shè)計(jì)模式,您將能夠更快地構(gòu)建可靠的 OO 應(yīng)用程序。但當(dāng)整個(gè)開發(fā)團(tuán)隊(duì)知道各種模式時(shí),您可以突然擁有非常高的帶寬會(huì)話。您不再需要討論將到處使用的所有類。相反,您可以與其他人談?wù)撃J??!拔乙谶@里引用一個(gè)單例(singleton),然后使用迭代器遍歷對象集合,然后……” 比遍歷構(gòu)成這些模式的類、方法和接口快很多。單是通信效率一項(xiàng)就值得花時(shí)間以團(tuán)隊(duì)的形式通過會(huì)話來研究模式。
減少痛苦的教訓(xùn)
每個(gè)設(shè)計(jì)模式都描述了一種經(jīng)過驗(yàn)證的解決常見問題的方法。因此,您無需擔(dān)心設(shè)計(jì)是不是正確的,只要您已經(jīng)選擇了提供所需優(yōu)點(diǎn)的模式。

缺陷

有句諺語說得好:“當(dāng)您手中拿著一把錘子時(shí),所有事物看上去都像釘子”。當(dāng)您認(rèn)為自己找到一個(gè)優(yōu)秀模式時(shí),您可能會(huì)嘗試到處使用它,即使在不應(yīng)當(dāng)使用它的位置。記住您必須考慮正在學(xué)習(xí)的模式的使用目的,不要為了使用模式而把這些模式強(qiáng)行應(yīng)用到應(yīng)用程序的各個(gè)部分中。

本文將介紹可用于改進(jìn) PHP 代碼的五個(gè)模式。每個(gè)模式都將介紹一個(gè)特定場景??梢栽? 下載 部分中獲得這些模式的 PHP 代碼。

要求

要發(fā)揮本文的最大功效并使用示例,需要在計(jì)算機(jī)中安裝以下軟件:

  • PHP V5 或更高版本(本文是使用 PHP V5.2.4 撰寫的)
  • 壓縮程序,例如 WinZIP(用于壓縮可下載的代碼歸檔)

注: 雖然您也可以使用純文本編輯器,但是我發(fā)現(xiàn)擁有語法高亮顯示和語法糾錯(cuò)功能的編輯器真的很有幫助。本文中的示例是使用 Eclipse PHP Development Tools (PDT) 編寫的。





回頁首


適配器模式

在需要將一類對象轉(zhuǎn)換成另一類對象時(shí),請使用適配器模式。通常,開發(fā)人員通過一系列賦值代碼來處理此過程,如清單 1 所示。適配器模式是整理此類代碼并在其他位置重用所有賦值代碼的優(yōu)秀方法。此外,它還將隱藏賦值代碼,如果同時(shí)還要設(shè)定格式,這樣可以極大地簡化工作。


清單 1. 使用代碼在對象之間賦值

                            
class AddressDisplay
{
    private $addressType;
    private $addressText;

    public function setAddressType($addressType)
    {
        $this->addressType = $addressType;
    }

    public function getAddressType()
    {
        return $this->addressType;
    }

    public function setAddressText($addressText)
    {
        $this->addressText = $addressText;
    }

    public function getAddressText()
    {
        return $this->addressText;
    }
}

class EmailAddress
{
    private $emailAddress;
    
    public function getEmailAddress()
    {
        return $this->emailAddress;
    }
    
    public function setEmailAddress($address)
    {
        $this->emailAddress = $address;
    }
}

$emailAddress = new EmailAddress();
/* Populate the EmailAddress object */
$address = new AddressDisplay();

            
              
                /* Here's the assignment code, where I'm assigning values from one object to another... */
              
            
            
$address->setAddressType("email");
$address->setAddressText($emailAddress->getEmailAddress());

          

此示例將使用 AddressDisplay 對象把地址顯示給用戶。 AddressDisplay 對象有兩部分:地址類型和一個(gè)格式化的地址字符串。

在實(shí)現(xiàn)模式(參見清單 2)后,PHP 腳本將不再需要擔(dān)心如何把 EmailAddress 對象轉(zhuǎn)換成 AddressDisplay 對象。那是件好事,尤其是在 AddressDisplay 對象發(fā)生更改時(shí)或者控制如何把 EmailAddress 對象轉(zhuǎn)換成 AddressDisplay 對象的規(guī)則發(fā)生更改時(shí)。記住,以模塊化風(fēng)格設(shè)計(jì)代碼的主要優(yōu)點(diǎn)之一就是,在業(yè)務(wù)領(lǐng)域發(fā)生一些更改時(shí)或者需要向軟件中添加新功能時(shí)盡可能少的使用更改。即使在執(zhí)行普通任務(wù)(例如把一個(gè)對象的屬性值賦給另一個(gè)對象)時(shí),也請考慮使用此模式。


清單 2. 使用適配器模式

                            
class EmailAddressDisplayAdapter extends AddressDisplay
{
    public function __construct($emailAddr)
    {
        $this->setAddressType("email");
        $this->setAddressText($emailAddr->getEmailAddress());
    }
}	

$email = new EmailAddress();
$email->setEmailAddress("user@example.com");

$address = new EmailAddressDisplayAdapter($email);

echo($address->getAddressType() . "/n") ;
echo($address->getAddressText());

          

圖 1 顯示了適配器模式的類圖。


圖 1. 適配器模式的類圖
適配器模式的類圖

替代方法

編寫適配器的替代方法 —— 并且是推薦方法 —— 是實(shí)現(xiàn)一個(gè)接口來修改行為,而不是擴(kuò)展對象。這是一種非常干凈的、創(chuàng)建適配器的方法并且沒有擴(kuò)展對象的缺點(diǎn)。使用接口的缺點(diǎn)之一是需要把實(shí)現(xiàn)添加到適配器類中,如圖 2 所示:


圖 2. 適配器模式(使用接口)
適配器模式(使用接口)





回頁首


迭代器模式

迭代器模式將提供一種通過對象集合或?qū)ο髷?shù)組封裝迭代的方法。如果需要遍歷集合中不同類型的對象,則使用這種模式尤為便利。

查看上面清單 1 中的電子郵件和物理地址示例。在添加迭代器模式之前,如果要遍歷個(gè)人地址,則可能要遍歷物理地址并顯示這些地址,然后遍歷個(gè)人電子郵件地址并顯示這些地址,然后遍歷個(gè)人 IM 地址并顯示這些地址。非常復(fù)雜的遍歷!

相反,通過實(shí)現(xiàn)迭代器,您只需要調(diào)用 while($itr->hasNext()) 并處理下一個(gè)條目 $itr->next() 返回。清單 3 中顯示了一個(gè)迭代器示例。迭代器功能強(qiáng)大,因?yàn)槟梢蕴砑右闅v的新類型條目,并且無需更改遍歷條目的代碼。例如,在 Person 示例中,可以添加 IM 地址數(shù)組;只需更新迭代器,無需更改遍歷地址的任何代碼。


清單 3. 使用迭代器模式遍歷對象

                            
class PersonAddressIterator implements AddressIterator
{
    private $emailAddresses;
    private $physicalAddresses;
    private $position;
    
    public function __construct($emailAddresses)
    {
        $this->emailAddresses = $emailAddresses;
        $this->position = 0;
    }
    
    public function hasNext()
    {
        if ($this->position >= count($this->emailAddresses) || 
            $this->emailAddresses[$this->position] == null) {
            return false;
        } else {
            return true;
        }
    }
    
    public function next()
    {
        $item = $this->emailAddresses[$this->position];
        $this->position = $this->position + 1;
        return $item;
    }
    
}

          

如果把 Person 對象修改為返回 AddressIterator 接口的實(shí)現(xiàn),則在將實(shí)現(xiàn)擴(kuò)展為遍歷附加對象時(shí)無需修改使用迭代器的應(yīng)用程序代碼。您可以使用一個(gè)混合迭代器,它封裝了遍歷清單 3 中列出的每種地址的迭代器。本文提供了此類應(yīng)用示例(請參閱 下載 )。

圖 3 顯示了迭代器模式的類圖。


圖 3. 迭代器模式的類圖
迭代器模式的類圖





回頁首


裝飾器 (decorator) 模式

考慮清單 4 中的代碼樣例。這段代碼的目的是要把許多功能添加到 Build Your Own Car 站點(diǎn)的汽車中。每個(gè)汽車模型都有更多功能及相關(guān)價(jià)格。如果只針對兩個(gè)模型,使用 if then 語句添加這些功能十分平常。但是,如果出現(xiàn)了新模型,則必須返回查看代碼并確保語句對新模型工作正常。


清單 4. 使用裝飾器模式添加功能

                            
require('classes.php');

$auto = new Automobile();

$model = new BaseAutomobileModel();

$model = new SportAutomobileModel($model);

$model = new TouringAutomobileModel($model);

$auto->setModel($model);

$auto->printDescription();

          

進(jìn)入裝飾器模式,該模式允許您通過一個(gè)優(yōu)秀整潔的類將此功能添加到 AutomobileModel 。每個(gè)類僅僅關(guān)注其價(jià)格、選項(xiàng)以及添加到基本模型的方式。

圖 4 顯示了裝飾器模式的類圖。


圖 4. 裝飾器模式的類圖
裝飾器模式的類圖

裝飾器模式的優(yōu)點(diǎn)是可以輕松地同時(shí)跟蹤庫的多個(gè)裝飾器。

如果您擁有流對象的使用經(jīng)驗(yàn),則一定使用過裝飾器。大多數(shù)流結(jié)構(gòu)(例如輸出流)都是接受基本輸入流的裝飾器,然后通過添加附加功能來裝飾它 —— 例如從文件輸入流、從緩沖區(qū)輸入流,等等。





回頁首


委托模式

委托模式將提供一種基于各種條件委托行為的方法??紤]清單 5 中的代碼。這段代碼包含幾個(gè)條件。根據(jù)條件,代碼將選擇相應(yīng)類型的對象來處理請求。


清單 5. 使用條件語句來發(fā)送送貨請求

                            
pkg = new Package("Heavy Package");
$pkg->setWeight(100);

if ($pkg->getWeight() > 99)
{
	echo( "Shipping " . $pkg->getDescription() . " by rail.");
} else {
	echo("Shipping " . $pkg->getDescription() . " by truck");
}

          

使用委托模式,對象將內(nèi)在化(internalize)此發(fā)送過程,方法為在調(diào)用如清單 6 中的 useRail() 之類的方法時(shí)設(shè)置對相應(yīng)對象的內(nèi)部引用。如果處理各個(gè)包的條件發(fā)生更改或者使用新的送貨類型時(shí),則使用此模式尤為便利。


清單 6. 使用委托模式來發(fā)送送貨請求

                            
require_once('classes.php');

$pkg = new Package("Heavy Package");
$pkg->setWeight(100);

$shipper = new ShippingDelegate();

if ($pkg->getWeight() > 99)
{
	$shipper->useRail();
}

$shipper->deliver($pkg);

          

委托將通過調(diào)用 useRail() useTruck() 方法來切換處理工作的類,從而提供動(dòng)態(tài)更改行為的優(yōu)點(diǎn)。

圖 5 顯示了委托模式的類圖。


圖 5. 委托模式的類圖
委托模式的類圖





回頁首


狀態(tài)模式

狀態(tài)模式類似于命令模式,但是意圖截然不同??紤]下面的代碼。


清單 7. 使用代碼來構(gòu)建機(jī)器人

                            
class Robot 
{

	private $state;

	public function powerUp()
	{
		if (strcmp($state, "poweredUp") == 0)
		{
			echo("Already powered up.../n");
			/* Implementation... */
		} else if ( strcmp($state, "powereddown") == 0) {
			echo("Powering up now.../n");
			/* Implementation... */
		}
	}

	public function powerDown()
	{
		if (strcmp($state, "poweredUp") == 0)
		{
			echo("Powering down now.../n");
			/* Implementation... */
		} else if ( strcmp($state, "powereddown") == 0) {
			echo("Already powered down.../n");
			/* Implementation... */
		}
	}

	/* etc... */

}

          

在此清單中,PHP 代碼表示變成一輛汽車的強(qiáng)大機(jī)器人的操作系統(tǒng)。機(jī)器人可以啟動(dòng)、關(guān)閉、由汽車變成機(jī)器人以及由機(jī)器人變成汽車。代碼現(xiàn)已就緒,但是您會(huì)看到如果任何規(guī)則發(fā)生更改或者添加另一個(gè)狀態(tài)則會(huì)變得十分復(fù)雜。

現(xiàn)在查看清單 8,其中提供了相同的邏輯處理機(jī)器人的狀態(tài),但是這一次把邏輯放入狀態(tài)模式。清單 8 中的代碼完成的工作與初始代碼相同,但是用于處理狀態(tài)的邏輯已經(jīng)被放入每個(gè)狀態(tài)的一個(gè)對象中。為了演示使用設(shè)計(jì)模式的優(yōu)點(diǎn),假定不久以后,這些機(jī)器人發(fā)現(xiàn)它們不應(yīng)在處于機(jī)器人模式時(shí)關(guān)閉。實(shí)際上,如果它們關(guān)閉,它們必須先切換到汽車模式。如果它們已經(jīng)處于汽車模式下,則機(jī)器人將關(guān)閉。使用狀態(tài)模式,對代碼的更改十分微小。


清單 8. 使用狀態(tài)模式處理機(jī)器人的狀態(tài)

                            
$robot = new Robot();
echo("/n");
$robot->powerUp();
echo("/n");
$robot->turnIntoRobot();
echo("/n");
$robot->turnIntoRobot(); /* This one will just give me a message */
echo("/n");
$robot->turnIntoVehicle();
echo("/n");

          


清單 9. 對一個(gè)狀態(tài)對象的微小更改
                            
class NormalRobotState implements RobotState
{
    private $robot;

    public function __construct($robot)
    {
        $this->robot = $robot;
    }

    public function powerUp()
    {
        /* implementation... */
    }
    public function powerDown()  
    {
        
            
              
                /* First, turn into a vehicle */ $this->robot->setState(new VehicleRobotState($this->robot)); $this->robot->powerDown();
              
            
            
    }
    
    public function turnIntoVehicle()  
    {
        /* implementation... */
    }
    
    public function turnIntoRobot() 
    {
        /* implementation... */
    }
}

          

圖 6 中一個(gè)不太明顯的地方就是狀態(tài)模式中的每個(gè)對象都有對上下文對象(機(jī)器人)的引用,因此每個(gè)對象都可以把狀態(tài)提升到相應(yīng)的狀態(tài)。


圖 6. 狀態(tài)模式的類圖
狀態(tài)模式的類圖

結(jié)束語

在 PHP 代碼中使用設(shè)計(jì)模式可以使代碼更容易閱讀、更易維護(hù)。通過使用已經(jīng)建立的模式,您將從通用的設(shè)計(jì)結(jié)構(gòu)中獲益,從而允許團(tuán)隊(duì)的其他開發(fā)人員了解代碼的意圖。它還使您可以從其他設(shè)計(jì)者完成的工作中獲益,因此無需從失敗的設(shè)計(jì)理念中吸取教訓(xùn)。

來源: http://www.ibm.com/developerworks/cn/opensource/os-php-designpatterns


另外五個(gè) PHP 設(shè)計(jì)模式


更多文章、技術(shù)交流、商務(wù)合作、聯(lián)系博主

微信掃碼或搜索:z360901061

微信掃一掃加我為好友

QQ號聯(lián)系: 360901061

您的支持是博主寫作最大的動(dòng)力,如果您喜歡我的文章,感覺我的文章對您有幫助,請用微信掃描下面二維碼支持博主2元、5元、10元、20元等您想捐的金額吧,狠狠點(diǎn)擊下面給點(diǎn)支持吧,站長非常感激您!手機(jī)微信長按不能支付解決辦法:請將微信支付二維碼保存到相冊,切換到微信,然后點(diǎn)擊微信右上角掃一掃功能,選擇支付二維碼完成支付。

【本文對您有幫助就好】

您的支持是博主寫作最大的動(dòng)力,如果您喜歡我的文章,感覺我的文章對您有幫助,請用微信掃描上面二維碼支持博主2元、5元、10元、自定義金額等您想捐的金額吧,站長會(huì)非常 感謝您的哦?。。?/p>

發(fā)表我的評論
最新評論 總共0條評論
主站蜘蛛池模板: 欧美日韩中文在线视频 | 成人影院wwwwwwwwwww| 欧美日韩一区二区视频在线观看 | 天堂va在线高清一区 | 亚洲精品免费在线 | 欧美另类videosbestsex久久 | www.com黄色 | 亚洲免费人成在线视频观看 | 美女一区| 日日麻批免费视频 | 婷婷六月天 | 成人欧美在线观看 | vidz 98hd| 色资源网站 | 色蜜桃网 | 国产日韩欧美在线 | 久久免费看少妇高潮A片特黄多 | 欧美专区视频 | 在线亚洲一区二区 | 热99精品| 4hu在线| 国产一级特黄aa大片爽爽 | 一区二区三区四区高清视频 | 欧美a大片 | 狠狠干奇米 | 日本高清视频在线播放 | 91中文视频 | 亚洲免费看片网站 | 亚洲最新永久观看在线 | 亚洲高清一区二区三区 | 亚洲免费av在线 | 一区二区三区亚洲 | 亚洲人性生活视频 | 99精品久久秒播无毒不卡 | www.av在线免费观看 | 亚洲第一黄色网 | 天天操网| 午夜精品久久久久久99热7777 | 欧美一级毛片欧美毛片视频 | 国产国产精品人在线观看 | 99这里只有精品视频 |