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