當(dāng)前位置:工程項(xiàng)目OA系統(tǒng) > 泛普各地 > 江西OA系統(tǒng) > 鷹潭OA > 鷹潭網(wǎng)站建設(shè)公司
構(gòu)造開(kāi)發(fā)模板 五種PHP設(shè)計(jì)模式
申請(qǐng)免費(fèi)試用、咨詢(xún)電話:400-8352-114
鷹潭網(wǎng)站建設(shè)www.diyphp.net
設(shè)計(jì)形式只是為 Java 架構(gòu)師預(yù)備的 —— 至少您能夠不斷如許以為。實(shí)踐上,設(shè)計(jì)形式關(guān)于每小我都十分有效。假如這些東西不是 “架構(gòu)太空人” 的專(zhuān)利,那么它們又是什么?為什么說(shuō)它們?cè)?PHP 使用順序中十分有效?本文分析了這些問(wèn)題。
設(shè)計(jì)形式 一書(shū)將設(shè)計(jì)形式引入軟件社區(qū),該書(shū)的作者是 Erich Gamma、Richard Helm、Ralph Johnson 和 John Vlissides Design(俗稱(chēng) “四人幫”)。所引見(jiàn)的設(shè)計(jì)形式背面的中心概念十分簡(jiǎn)略。經(jīng)由多年的軟件開(kāi)拓理論,Gamma 等人發(fā)現(xiàn)了某些具有固定設(shè)計(jì)的形式,就像修建師設(shè)計(jì)房子和修建物一樣,可認(rèn)為浴室的地位或廚房的結(jié)構(gòu)方法開(kāi)拓模板。運(yùn)用這些模板或許說(shuō)設(shè)計(jì)形式 意味著可以更快地設(shè)計(jì)更好的修建物。相同的概念也合用于軟件。
設(shè)計(jì)形式不只代表著更快開(kāi)拓強(qiáng)健軟件的有效辦法,并且還供應(yīng)了以友愛(ài)的術(shù)語(yǔ)封裝大型理念的辦法。例如,您可以說(shuō)您正在編寫(xiě)一個(gè)供應(yīng)松懈耦合的音訊傳遞系統(tǒng),也可以說(shuō)你正在編寫(xiě)稱(chēng)號(hào)為察看者 的形式。
用較小的示例展現(xiàn)形式的價(jià)值長(zhǎng)短常堅(jiān)苦的。這往往有些牛鼎烹雞的意味,由于形式實(shí)踐上是在大型代碼庫(kù)中發(fā)揚(yáng)效果的。本文不展現(xiàn)大型使用順序,所以您需求思考的是在您本人的大型使用順序中使用示例道理的辦法 —— 而不是本文演示的代碼自身。這不是說(shuō)您不該該在小使用順序中運(yùn)用形式。良多優(yōu)越的使用順序都以小使用順序?yàn)槠瘘c(diǎn),逐步開(kāi)展到大型使用順序,所以沒(méi)有來(lái)由不以此類(lèi)扎實(shí)的編碼理論為根底。 既然您曾經(jīng)調(diào)查了設(shè)計(jì)形式以及它們的有效之處,目前我們來(lái)看看 PHP V5 的五種常用形式。
工場(chǎng)形式
開(kāi)始在設(shè)計(jì)形式 一書(shū)中,很多設(shè)計(jì)形式都鼓舞運(yùn)用松懈耦合。要了解這個(gè)概念,讓我們最好談一下很多開(kāi)拓人員從事大型系統(tǒng)的艱辛過(guò)程。在更改一個(gè)代碼片段時(shí),就會(huì)發(fā)作問(wèn)題,系統(tǒng)其他局部 —— 您曾以為完全不相關(guān)的局部中也有能夠呈現(xiàn)級(jí)聯(lián)毀壞。
該問(wèn)題在于嚴(yán)密耦合 。系統(tǒng)某個(gè)局部中的函數(shù)和類(lèi)嚴(yán)峻依靠于系統(tǒng)的其他局部中函數(shù)和類(lèi)的行為和構(gòu)造。您需求一組形式,使這些類(lèi)可以互相通訊,但不但愿將它們嚴(yán)密綁定在一同,以防止呈現(xiàn)聯(lián)鎖。 在大型系統(tǒng)中,很多代碼依靠于少量幾個(gè)要害類(lèi)。需求更改這些類(lèi)時(shí),能夠會(huì)呈現(xiàn)堅(jiān)苦。例如,假定您有一個(gè)從文件讀取的 User 類(lèi)。您但愿將其更改為從數(shù)據(jù)庫(kù)讀取的其他類(lèi),然則,一切的代碼都援用從文件讀取的原始類(lèi)。這時(shí)分,運(yùn)用工場(chǎng)形式會(huì)很便利。
工場(chǎng)形式 是一品種,它具有為您創(chuàng)立對(duì)象的某些辦法。您可以運(yùn)用工場(chǎng)類(lèi)創(chuàng)立對(duì)象,而不直接運(yùn)用 new。如許,假如您想要更改所創(chuàng)立的對(duì)象類(lèi)型,只需更改該工場(chǎng)即可。運(yùn)用該工場(chǎng)的一切代碼會(huì)主動(dòng)更改。
清單 1 顯示工場(chǎng)類(lèi)的一個(gè)示列。等式的效勞器端包羅兩個(gè)局部:數(shù)據(jù)庫(kù)和一組 PHP 頁(yè)面,這些頁(yè)面答應(yīng)您添加反應(yīng)、懇求反應(yīng)列表并獲取與特定反應(yīng)相關(guān)的文章。
清單 1. Factory1.php
interface IUser
{
function getName();
}
class User implements IUser
{
public function __construct( $id ) { }
public function getName()
{
return "Jack";
}
}
class UserFactory
{
public static function Create( $id )
{
return new User( $id );
}
}
$uo = UserFactory::Create( 1 );
echo( $uo->getName()."\n" );
?>
IUser 接口界說(shuō)用戶(hù)對(duì)象應(yīng)執(zhí)行什么操作。IUser 的完成稱(chēng)為 User,UserFactory 工場(chǎng)類(lèi)則創(chuàng)立 IUser 對(duì)象。此關(guān)系可以用圖 1 中的 UML 透露表現(xiàn)。
圖 1. 工場(chǎng)類(lèi)及其相關(guān) IUser 接口和用戶(hù)類(lèi)
假如您運(yùn)用 php 分析器在敕令行上運(yùn)轉(zhuǎn)此代碼,將獲得如下后果:
Jack
%
測(cè)試代碼會(huì)向工場(chǎng)懇求 User 對(duì)象,并輸出 getName 辦法的后果。
有一種工場(chǎng)形式的變體運(yùn)用工場(chǎng)辦法。類(lèi)中的這些公共靜態(tài)辦法結(jié)構(gòu)該類(lèi)型的對(duì)象。假如創(chuàng)立此類(lèi)型的對(duì)象十分主要,此辦法十分有效。例如,假定您需求先創(chuàng)立對(duì)象,然后設(shè)置很多屬性。此版本的工場(chǎng)形式會(huì)將該歷程封裝在單個(gè)地位中,如許,不必復(fù)制復(fù)雜的初始化代碼,也不用將復(fù)制好的代碼在在代碼庫(kù)中四處粘貼。 清單 2 顯示運(yùn)用工場(chǎng)辦法的一個(gè)示例。
清單 2. Factory2.php
interface IUser
{
function getName();
}
class User implements IUser
{
public static function Load( $id )
{
return new User( $id );
}
public static function Create( )
{
return new User( null );
}
public function __construct( $id ) { }
public function getName()
{
return "Jack";
}
}
$uo = User::Load( 1 );
echo( $uo->getName()."\n" );
?>
這段代碼要簡(jiǎn)略得多。它僅有一個(gè)接口 IUser 和一個(gè)完成此接口的 User 類(lèi)。User 類(lèi)有兩個(gè)創(chuàng)立對(duì)象的靜態(tài)辦法。此關(guān)系可用圖 2 中的 UML 透露表現(xiàn)。
圖 2. IUser 接口和帶有工場(chǎng)辦法的 user 類(lèi)
在敕令行中運(yùn)轉(zhuǎn)劇本發(fā)生的后果與清單 1 的后果一樣,如下所示:
Jack
%
如上所述,有時(shí)此類(lèi)形式在規(guī)劃較小的情況中似乎有些牛鼎烹雞。但是,最好照樣進(jìn)修這種扎實(shí)的編碼方式,以便使用于恣意規(guī)劃的項(xiàng)目中。
單位素形式
某些使用順序資本是獨(dú)有的,由于有且只要一個(gè)此類(lèi)型的資本。例如,經(jīng)過(guò)數(shù)據(jù)庫(kù)句柄到數(shù)據(jù)庫(kù)的銜接是獨(dú)有的。您但愿在使用順序中共享數(shù)據(jù)庫(kù)句柄,由于在堅(jiān)持銜接翻開(kāi)或封閉時(shí),它是一種開(kāi)支,在獲取單個(gè)頁(yè)面的進(jìn)程中更是如斯。
單位素形式可以知足此要求。假如使用順序每次包括且僅包括一個(gè)對(duì)象,那么這個(gè)對(duì)象就是一個(gè)單位素(Singleton)。清單 3 中的代碼顯示了 PHP V5 中的一個(gè)數(shù)據(jù)庫(kù)銜接單位素。
清單 3. Singleton.php
<?php
require_once("DB.php");
class DatabaseConnection
{
public static function get()
{
static $db = null;
if ( $db == null )
$db = new DatabaseConnection();
return $db;
}
private $_handle = null;
private function __construct()
{
$dsn = 'mysql://root:password@localhost/photos';
$this->_handle =& DB::Connect( $dsn, array() );
}
public function handle()
{
return $this->_handle;
}
}
print( "Handle = ".DatabaseConnection::get()->handle()."\n" );
print( "Handle = ".DatabaseConnection::get()->handle()."\n" );
?>
此代碼顯示名為 DatabaseConnection 的單個(gè)類(lèi)。您不克不及創(chuàng)立自已的 DatabaseConnection,由于結(jié)構(gòu)函數(shù)是專(zhuān)用的。但運(yùn)用靜態(tài) get 辦法,您可以取得且僅取得一個(gè) DatabaseConnection 對(duì)象。此代碼的 UML 如圖 3 所示。
圖 3. 數(shù)據(jù)庫(kù)銜接單位素
在兩次挪用間,handle 辦法返回的數(shù)據(jù)庫(kù)句柄是一樣的,這就是最好的證實(shí)。您可以在敕令行中運(yùn)轉(zhuǎn)代碼來(lái)察看這一點(diǎn)。
Handle = Object id #3
Handle = Object id #3
%
返回的兩個(gè)句柄是統(tǒng)一對(duì)象。假如您在整個(gè)使用順序中運(yùn)用數(shù)據(jù)庫(kù)銜接單位素,那么就可以在任何當(dāng)?shù)刂赜媒y(tǒng)一句柄。
您可以運(yùn)用全局變量存儲(chǔ)數(shù)據(jù)庫(kù)句柄,然則,該辦法僅合用于較小的使用順序。在較大的使用順序中,應(yīng)防止運(yùn)用全局變量,并運(yùn)用對(duì)象和辦法拜訪資本。
察看者形式
察看者形式為您供應(yīng)了防止組件之間嚴(yán)密耦合的另一種辦法。該形式十分簡(jiǎn)略:一個(gè)對(duì)象經(jīng)過(guò)添加一個(gè)辦法(該辦法答應(yīng)另一個(gè)對(duì)象,即察看者 注冊(cè)本人)使自身變得可察看。當(dāng)可察看的對(duì)象更改時(shí),它會(huì)將音訊發(fā)送到已注冊(cè)的察看者。這些察看者運(yùn)用該信息執(zhí)行的操作與可察看的對(duì)象無(wú)關(guān)。后果是對(duì)象可以互相對(duì)話,而不用調(diào)查緣由。 一個(gè)簡(jiǎn)略示例是系統(tǒng)中的用戶(hù)列表。清單 4 中的代碼顯示一個(gè)用戶(hù)列表,添加用戶(hù)時(shí),它將發(fā)送出一條音訊。添加用戶(hù)時(shí),經(jīng)過(guò)發(fā)送音訊的日記察看者可以察看此列表。
清單 4. Observer.php
<?php
interface IObserver
{
function onChanged( $sender, $args );
}
interface IObservable
{
function addObserver( $observer );
}
class UserList implements IObservable
{
private $_observers = array();
public function addCustomer( $name )
{
foreach( $this->_observers as $obs )
$obs->onChanged( $this, $name );
}
public function addObserver( $observer )
{
$this->_observers []= $observer;
}
}
class UserListLogger implements IObserver
{
public function onChanged( $sender, $args )
{
echo( "'$args' added to user list\n" );
}
}
$ul = new UserList();
$ul->addObserver( new UserListLogger() );
$ul->addCustomer( "Jack" );
?>
此代碼界說(shuō)四個(gè)元素:兩個(gè)接口和兩個(gè)類(lèi)。IObservable 接口界說(shuō)可以被察看的對(duì)象,UserList 完成該接口,以便將自身注冊(cè)為可察看。IObserver 列表界說(shuō)要經(jīng)過(guò)如何的辦法才干成為察看者,UserListLogger 完成 IObserver 接口。圖 4 的 UML 中展現(xiàn)了這些元素。
圖 4. 可察看的用戶(hù)列表和用戶(hù)列表事情日記順序
假如在敕令行中運(yùn)轉(zhuǎn)它,您將看到以下輸出:
'Jack' added to user list
%
測(cè)試代碼創(chuàng)立 UserList,并將 UserListLogger 察看者添加到個(gè)中。然后添加一個(gè)消費(fèi)者,并將這一更改告訴 UserListLogger。
看法到 UserList 不曉得日記順序?qū)?zhí)行什么操作很要害。能夠存在一個(gè)或多個(gè)執(zhí)行其他操作的偵聽(tīng)順序。例如,您能夠有一個(gè)向新用戶(hù)發(fā)送音訊的察看者,歡送新用戶(hù)運(yùn)用該系統(tǒng)。這種辦法的價(jià)值在于 UserList 疏忽一切依靠它的對(duì)象,它首要存眷在列表更改時(shí)維護(hù)用戶(hù)列表并發(fā)送音訊這一任務(wù)。
此形式不限于內(nèi)存中的對(duì)象。它是在較大的使用順序中運(yùn)用的數(shù)據(jù)庫(kù)驅(qū)動(dòng)的音訊查詢(xún)系統(tǒng)的根底。
敕令鏈形式
敕令鏈 形式以松懈耦合主題為根底,發(fā)送音訊、敕令和懇求,或經(jīng)過(guò)一組處置順序發(fā)送恣意內(nèi)容。每個(gè)處置順序都邑自行判別本人可否處置懇求。假如可以,該懇求被處置,歷程中止。您可認(rèn)為系統(tǒng)添加或移除處置順序,而不影響其他處置順序。清單 5 顯示了此形式的一個(gè)示例。
清單 5. Chain.php
<?php
interface ICommand
{
function onCommand( $name, $args );
}
class CommandChain
{
private $_commands = array();
public function addCommand( $cmd )
{
$this->_commands []= $cmd;
}
public function runCommand( $name, $args )
{
foreach( $this->_commands as $cmd )
{
if ( $cmd->onCommand( $name, $args ) )
return;
}
}
}
class UserCommand implements ICommand
{
public function onCommand( $name, $args )
{
if ( $name != 'addUser' ) return false;
echo( "UserCommand handling 'addUser'\n" );
return true;
}
}
class MailCommand implements ICommand
{
public function onCommand( $name, $args )
{
if ( $name != 'mail' ) return false;
echo( "MailCommand handling 'mail'\n" );
return true;
}
}
$cc = new CommandChain();
$cc->addCommand( new UserCommand() );
$cc->addCommand( new MailCommand() );
$cc->runCommand( 'addUser', null );
$cc->runCommand( 'mail', null );
?>
此代碼界說(shuō)維護(hù) ICommand 對(duì)象列表的 CommandChain 類(lèi)。兩個(gè)類(lèi)都可以完成 ICommand 接口 —— 一個(gè)對(duì)郵件的懇求作出呼應(yīng),另一個(gè)對(duì)添加用戶(hù)作出呼應(yīng)。 圖 5 給出了 UML。
圖 5. 敕令鏈及其相關(guān)敕令
假如您運(yùn)轉(zhuǎn)包括某些測(cè)試代碼的劇本,則會(huì)獲得以下輸出:
UserCommand handling 'addUser'
MailCommand handling 'mail'
%
代碼起首創(chuàng)立 CommandChain 對(duì)象,并為它添加兩個(gè)敕令對(duì)象的實(shí)例。然后運(yùn)轉(zhuǎn)兩個(gè)敕令以檢查誰(shuí)對(duì)這些敕令作出了呼應(yīng)。假如敕令的稱(chēng)號(hào)匹配 UserCommand 或 MailCommand,則代碼掉敗,不發(fā)作任何操作。 為處置懇求而創(chuàng)立可擴(kuò)展的架構(gòu)時(shí),敕令鏈形式很有價(jià)值,運(yùn)用它可以處理很多問(wèn)題。
戰(zhàn)略形式
我們講述的最終一個(gè)設(shè)計(jì)形式是戰(zhàn)略 形式。在此形式中,算法是從復(fù)雜類(lèi)提取的,因此可以便利地交換。例如,假如要更改查找引擎中陳列頁(yè)的辦法,則戰(zhàn)略形式是一個(gè)不錯(cuò)的選擇??紤]一下查找引擎的幾個(gè)局部 —— 一局部遍歷頁(yè)面,一局部對(duì)每頁(yè)陳列,另一局部基于陳列的后果排序。在復(fù)雜的示例中,這些局部都在統(tǒng)一個(gè)類(lèi)中。經(jīng)過(guò)運(yùn)用戰(zhàn)略形式,您可將陳列局部放入另一個(gè)類(lèi)中,以便更改頁(yè)陳列的方法,而不影響查找引擎的其他代碼。
作為一個(gè)較簡(jiǎn)略的示例,清單 6 顯示了一個(gè)用戶(hù)列表類(lèi),它供應(yīng)了一個(gè)依據(jù)一組即插即用的戰(zhàn)略查找一組用戶(hù)的辦法。
清單 6. Strategy.php
<?php
interface IStrategy
{
function filter( $record );
}
class FindAfterStrategy implements IStrategy
{
private $_name;
public function __construct( $name )
{
$this->_name = $name;
}
public function filter( $record )
{
return strcmp( $this->_name, $record ) <= 0;
}
}
class RandomStrategy implements IStrategy
{
public function filter( $record )
{
return rand( 0, 1 ) >= 0.5;
}
}
class UserList
{
private $_list = array();
public function __construct( $names )
{
if ( $names != null )
{
foreach( $names as $name )
{
$this->_list []= $name;
}
}
}
public function add( $name )
{
$this->_list []= $name;
}
public function find( $filter )
{
$recs = array();
foreach( $this->_list as $user )
{
if ( $filter->filter( $user ) )
$recs []= $user;
}
return $recs;
}
}
$ul = new UserList( array( "Andy", "Jack", "Lori", "Megan" ) );
$f1 = $ul->find( new FindAfterStrategy( "J" ) );
print_r( $f1 );
$f2 = $ul->find( new RandomStrategy() );
print_r( $f2 );
?>
圖 6. 用戶(hù)列表和用于選擇用戶(hù)的戰(zhàn)略
UserList 類(lèi)是打包稱(chēng)號(hào)數(shù)組的一個(gè)包裝器。它完成 find 辦法,該辦法應(yīng)用幾個(gè)戰(zhàn)略之一來(lái)選擇這些稱(chēng)號(hào)的子集。這些戰(zhàn)略由 IStrategy 接口界說(shuō),該接口有兩個(gè)完成:一個(gè)隨機(jī)選擇用戶(hù),另一個(gè)依據(jù)指命名稱(chēng)選擇這以后的一切稱(chēng)號(hào)。運(yùn)轉(zhuǎn)測(cè)試代碼時(shí),將獲得以下輸出:
Array
(
[0] => Jack
[1] => Lori
[2] => Megan
)
Array
(
[0] => Andy
[1] => Megan
)
%
測(cè)試代碼為兩個(gè)戰(zhàn)略運(yùn)轉(zhuǎn)統(tǒng)一用戶(hù)列表,并顯示后果。在第一種狀況中,戰(zhàn)略查找陳列在 J 后的任何稱(chēng)號(hào),所以您將獲得 Jack、Lori 和 Megan。第二個(gè)戰(zhàn)略隨機(jī)拔取稱(chēng)號(hào),每次會(huì)發(fā)生分歧的后果。在這種狀況下,后果為 Andy 和 Megan。
戰(zhàn)略形式十分合適復(fù)雜數(shù)據(jù)治理系統(tǒng)或數(shù)據(jù)處置系統(tǒng),二者在數(shù)據(jù)挑選、查找或處置的方法方面需求較高的靈敏性。
完畢語(yǔ)
本文引見(jiàn)的僅僅是 PHP 使用順序中運(yùn)用的幾種最經(jīng)常見(jiàn)的設(shè)計(jì)形式。在設(shè)計(jì)形式 一書(shū)中演示了更多的設(shè)計(jì)形式。不要因架構(gòu)的奧秘性而拋棄。形式是一種絕妙的理念,合用于任何編程言語(yǔ)、任何技藝程度。
- 1JavaScript 性能提升技巧
- 2每個(gè)cookie都是一個(gè)名/值對(duì)
- 3P2P網(wǎng)貸的營(yíng)銷(xiāo)戰(zhàn)略特點(diǎn)
- 4HTTPS(安全HTTP)和SSL/TLS(安全套接層/傳輸層安全)
- 5企業(yè)建站的重要性
- 6瀏覽器開(kāi)發(fā)工具的秘密
- 7p2p網(wǎng)貸系統(tǒng)可分為三部分
- 8玩具租賃電商平臺(tái)是什么
- 9P2P網(wǎng)貸的特點(diǎn)
- 10Dreamweaver插件
- 11家居家裝類(lèi)網(wǎng)站融入社區(qū)風(fēng)格方案
- 12房地產(chǎn)行業(yè)微信營(yíng)銷(xiāo)方案3
- 13玩具租賃系統(tǒng)功能列表
- 14Windows Azure 網(wǎng)站上運(yùn)行 CakePHP
- 15PHP與XML聯(lián)手進(jìn)行網(wǎng)站編程
- 16P2P網(wǎng)貸發(fā)展歷程
- 17網(wǎng)站制作絕對(duì)不可以犯的編程錯(cuò)誤2
- 18Zend2.0的MVC完整過(guò)程。
- 19常見(jiàn)的 Android 新手誤區(qū)
- 20Android訪問(wèn)php取回json數(shù)據(jù)
- 21企業(yè)四網(wǎng)合一網(wǎng)站升級(jí)版1
- 22最新動(dòng)態(tài)-久途遷新址
- 23網(wǎng)貸平臺(tái)主要運(yùn)營(yíng)模式主要有兩類(lèi)---債權(quán)轉(zhuǎn)讓模式
- 24O2O已經(jīng)成為電子商務(wù)網(wǎng)站的下一個(gè)掘金點(diǎn)
- 25百度算法更新,為什么站被降權(quán)?
- 26泛普軟件-U2ME網(wǎng)站設(shè)計(jì)方案計(jì)劃表
- 27地方生活優(yōu)惠電子商務(wù)網(wǎng)站需求分析
- 28Linux系統(tǒng)平安Shell劇本用于Linux系統(tǒng)的平安初始化劇本
- 29解決玩具租賃行業(yè)痛點(diǎn)
- 30企業(yè)做網(wǎng)站有沒(méi)有用?
成都公司:成都市成華區(qū)建設(shè)南路160號(hào)1層9號(hào)
重慶公司:重慶市江北區(qū)紅旗河溝華創(chuàng)商務(wù)大廈18樓