演算法參考文獻
10是卷,就是創刊以來的總刊數(或者是創刊第幾年,很多時候一年是一卷,或者半年,每個雜志社都不同)。
3是指在某一年的第幾期,是年度內的
對於《計算機輔助設計與圖形學學報》來說,它是創刊於1989年,是以年度為一卷。在1998年是雙月刊,說明該雜志是6月份出版。(現在是月刊)
如滿意回答,還望採納
㈡ 求問Rankboost演算法是在哪篇文獻中提出的。另外求該文獻的電子版或者按照參考文獻的格式列出。
剛好需要引用這篇論文,就去找了一下,希版望可以採納。權
[1] Y. Freund, R. lyer, et al. A Efficient Boosting Algorithm for Combining Preferences, JMLR 2003.
㈢ 數據挖掘參考文獻有哪些
參考文獻
[1] 李嶶,李宛州.基於數據倉庫技術的進銷存系統的設計與實現.2001(10):93-94
[2]Jiawei Han.數據挖掘概念與技術.機械工業出版社2001,8
[3]W.H.Inmon.數據倉庫.機械工業出版社2000,5
[4]林字等編著.數據倉庫原理與實踐.北京:人民郵電出版社,2003
[5]張春陽,周繼恩,劉貴全,蔡慶生.基於數據倉庫的決策支持系統的構建,計算機工程.2002(4):249-252
[6]陳德軍,盛翊智,陳綿雲.基於數據倉庫的OLAP在DSS中的應用研究.2003(1):30-31
[7]朱明,數據挖掘.合肥:中國科技大學出版社2002,5
[8] 陳京民等.數據倉庫與數據挖掘技術[M].北京:電子工業出版社,2002.
[9] 毛國君等.數據挖掘原理與演算法[M].北京:清華大學出版社,2005.
[10] 陳文偉等.數據挖掘技術[M].北京:北京工業大學出版社,2002.
㈣ 計算機專業研究生參考文獻里沒有演算法代碼怎麼辦
這個真的很難說,因為演算法還是有很大的應用領域的。比如說信息安全領域、自動內控制領域、人工容智能領域等等,後現代化的高科技領域都離不開演算法,其實你現在困惑是這個專業的學生普遍具備的,絕大多數的計算機專業或者非計算機專業的學生在本科階段並沒有對編程有太多的深入學習,本科的變成課程大多是一些比較基礎的,做一些簡單的PLC還可以。
研究生的演算法研究也不是一直都這么枯燥的,面對現階段的不可逆演算法等全新課程雖然有點枯燥,但是你只要把這個瓶頸期度過就好了。
演算法,一旦成為高尖端人才,之後的事情我不說你也知道。即便將來不再這個領域做了,也還可以改行作別的,從事自動化控制、過程裝備設計研發、人工智慧設備程序開發、程序安全性檢驗、系統安全/穩定性檢驗等工作,就業涉及研發、重型裝備製造、過程裝備製造等多個領域。
㈤ 無線移動自組網路路由演算法參考文獻有哪些
無線移動自組網路路由演算法參考文獻
1 肖克江;熊忠陽;張玉芳;;多徑路由協議AOMDV的改進與性能分析[J];計算機工程與應用;2012年06期
2 田克;張寶賢;馬建;姚鄭;;無線多跳網路中的機會路由[J];軟體學報;2010年10期
【共引文獻】
1 陳偉;魏強;趙玉婷;;傳輸速率感知的機會路由候選路由節點選擇和排序[J];計算機應用;2011年11期
2 王英;黃群;李雲;曹儐;;一種新的協作的路由協議:C-DSR[J];計算機應用研究;2013年07期
3 蔡順;張三峰;董永強;吳國新;;面向編碼機會路由的無線Mesh網路廣播信道接入[J];軟體學報;2012年09期
4 李彬;王文傑;殷勤業;楊榮;楊小勇;王慧明;;無線感測器網路節點協作的節能路由傳輸[J];西安交通大學學報;2012年06期
-----------------------華麗的分割線-----------------
如果我的回答對您有幫助希望您可以採納,謝謝!
-----------------------豪華的分割線-----------------
以上是軟硬謙施團隊為你帶來的回答。
如果有什麼不懂的可以追問,以後有什麼問題可以向我提問或者向我的團隊提問。
贈人玫瑰,手有餘香!幫助別人,快樂自己!「軟硬謙施」歡迎您加入我們的團隊幫助更多的人!
5 劉琰;;基於網路編碼的流量感知路由協議研究設計[J];延安大學學報(自然科學版);2013年01期
㈥ 怎麼寫參考文獻《ct原理與演算法》
你可以隨便找一個國內權威的期刊,參考期刊中的論文文獻格式寫入即可。 當年我也參加了全國的數學建模競賽以及美國MCM數據建模競賽,都是這樣寫參考文獻的。
㈦ 弗洛伊德演算法的參考文獻
演算法導論,靠復後的位置制
原理是這樣:
可以這樣來看那個二維矩陣,有值則代表兩個點直接連接,無窮則代表不相連
那麼我現在創建一個空集合,然後將這個圖當中的節點,一個一個的加進來,加入一個節點後,需要做一件事情,就是遍歷這個二維矩陣,在矩陣當中的每一個位置重新計算對應的兩個點的距離,根據什麼重新計算呢,如果經過這個點,兩點間距離是否會變短
加入一個點,矩陣就全部被更新一次,再加入一個點再更新一次最短的,一直到所有的點都被加入到了集合里,那麼最後的這個矩陣,就是任意兩個節點的最短距離了
㈧ BCJR演算法的參考文獻
^^.Bahl, J.Cocke, F.Jelinek, and J.Raviv, Optimal Decoding of Linear Codes for minimizing symbol error rate, IEEE Transactions on Information Theory, vol. IT-20(2), pp.284-287, March 1974.
^Sichun Wang and François Patenaude, A Systematic Approach to Modified BCJR MAP Algorithms for Convolutional Codes,EURASIP Journal on Applied Signal Processing, vol. 2006, Article ID 95360, 15 pages, 2006.doi:10.1155/ASP/2006/95360
^P. Robertson, P. Hoeher and E. Villebrun, Optimal and Sub-Optimal Maximum A Posteriori Algorithms Suitable for Turbo Decoding, European Transactions on Telecommunications, Vol. 8, 1997.
㈨ 誰給我來點計算機的參考文獻啊
正則表達式基礎知識
一個正則表達式就是由普通字元(例如字元 a 到 z)以及特殊字元(稱為元字元)組成的文字模式。該模式描述在查找文字主體時待匹配的一個或多個字元串。正則表達式作為一個模板,將某個字元模式與所搜索的字元串進行匹配。如:
JScript VBScript 匹配
/^\[ \t]*$/ "^\[ \t]*$" 匹配一個空白行。
/\d{2}-\d{5}/ "\d{2}-\d{5}" 驗證一個ID 號碼是否由一個2位數字,一個連字元以及一個5位數字組成。
/<(.*)>.*<\/\1>/ "<(.*)>.*<\/\1>" 匹配一個 HTML 標記。
下表是元字元及其在正則表達式上下文中的行為的一個完整列表:
字元 描述
\ 將下一個字元標記為一個特殊字元、或一個原義字元、或一個 向後引用、或一個八進制轉義符。例如,'n' 匹配字元 "n"。'\n' 匹配一個換行符。序列 '\\' 匹配 "\" 而 "\(" 則匹配 "("。
^ 匹配輸入字元串的開始位置。如果設置了 RegExp 對象的 Multiline 屬性,^ 也匹配 '\n' 或 '\r' 之後的位置。
$ 匹配輸入字元串的結束位置。如果設置了RegExp 對象的 Multiline 屬性,$ 也匹配 '\n' 或 '\r' 之前的位置。
* 匹配前面的子表達式零次或多次。例如,zo* 能匹配 "z" 以及 "zoo"。* 等價於{0,}。
+ 匹配前面的子表達式一次或多次。例如,'zo+' 能匹配 "zo" 以及 "zoo",但不能匹配 "z"。+ 等價於 {1,}。
? 匹配前面的子表達式零次或一次。例如,"do(es)?" 可以匹配 "do" 或 "does" 中的"do" 。? 等價於 {0,1}。
{n} n 是一個非負整數。匹配確定的 n 次。例如,'o{2}' 不能匹配 "Bob" 中的 'o',但是能匹配 "food" 中的兩個 o。
{n,} n 是一個非負整數。至少匹配n 次。例如,'o{2,}' 不能匹配 "Bob" 中的 'o',但能匹配 "foooood" 中的所有 o。'o{1,}' 等價於 'o+'。'o{0,}' 則等價於 'o*'。
{n,m} m 和 n 均為非負整數,其中n <= m。最少匹配 n 次且最多匹配 m 次。例如,"o{1,3}" 將匹配 "fooooood" 中的前三個 o。'o{0,1}' 等價於 'o?'。請注意在逗號和兩個數之間不能有空格。
? 當該字元緊跟在任何一個其他限制符 (*, +, ?, {n}, {n,}, {n,m}) 後面時,匹配模式是非貪婪的。非貪婪模式盡可能少的匹配所搜索的字元串,而默認的貪婪模式則盡可能多的匹配所搜索的字元串。例如,對於字元串 "oooo",'o+?' 將匹配單個 "o",而 'o+' 將匹配所有 'o'。
. 匹配除 "\n" 之外的任何單個字元。要匹配包括 '\n' 在內的任何字元,請使用象 '[.\n]' 的模式。
(pattern) 匹配 pattern 並獲取這一匹配。所獲取的匹配可以從產生的 Matches 集合得到,在VBScript 中使用 SubMatches 集合,在JScript 中則使用 $0…$9 屬性。要匹配圓括弧字元,請使用 '\(' 或 '\)'。
(?:pattern) 匹配 pattern 但不獲取匹配結果,也就是說這是一個非獲取匹配,不進行存儲供以後使用。這在使用 "或" 字元 (|) 來組合一個模式的各個部分是很有用。例如, 'instr(?:y|ies) 就是一個比 'instry|instries' 更簡略的表達式。
(?=pattern) 正向預查,在任何匹配 pattern 的字元串開始處匹配查找字元串。這是一個非獲取匹配,也就是說,該匹配不需要獲取供以後使用。例如,'Windows (?=95|98|NT|2000)' 能匹配 "Windows 2000" 中的 "Windows" ,但不能匹配 "Windows 3.1" 中的 "Windows"。預查不消耗字元,也就是說,在一個匹配發生後,在最後一次匹配之後立即開始下一次匹配的搜索,而不是從包含預查的字元之後開始。
(?!pattern) 負向預查,在任何不匹配 pattern 的字元串開始處匹配查找字元串。這是一個非獲取匹配,也就是說,該匹配不需要獲取供以後使用。例如'Windows (?!95|98|NT|2000)' 能匹配 "Windows 3.1" 中的 "Windows",但不能匹配 "Windows 2000" 中的 "Windows"。預查不消耗字元,也就是說,在一個匹配發生後,在最後一次匹配之後立即開始下一次匹配的搜索,而不是從包含預查的字元之後開始
x|y 匹配 x 或 y。例如,'z|food' 能匹配 "z" 或 "food"。'(z|f)ood' 則匹配 "zood" 或 "food"。
[xyz] 字元集合。匹配所包含的任意一個字元。例如, '[abc]' 可以匹配 "plain" 中的 'a'。
[^xyz] 負值字元集合。匹配未包含的任意字元。例如, '[^abc]' 可以匹配 "plain" 中的'p'。
[a-z] 字元范圍。匹配指定范圍內的任意字元。例如,'[a-z]' 可以匹配 'a' 到 'z' 范圍內的任意小寫字母字元。
[^a-z] 負值字元范圍。匹配任何不在指定范圍內的任意字元。例如,'[^a-z]' 可以匹配任何不在 'a' 到 'z' 范圍內的任意字元。
\b 匹配一個單詞邊界,也就是指單詞和空格間的位置。例如, 'er\b' 可以匹配"never" 中的 'er',但不能匹配 "verb" 中的 'er'。
\B 匹配非單詞邊界。'er\B' 能匹配 "verb" 中的 'er',但不能匹配 "never" 中的 'er'。
\cx 匹配由 x 指明的控制字元。例如, \cM 匹配一個 Control-M 或回車符。x 的值必須為 A-Z 或 a-z 之一。否則,將 c 視為一個原義的 'c' 字元。
\d 匹配一個數字字元。等價於 [0-9]。
\D 匹配一個非數字字元。等價於 [^0-9]。
\f 匹配一個換頁符。等價於 \x0c 和 \cL。
\n 匹配一個換行符。等價於 \x0a 和 \cJ。
\r 匹配一個回車符。等價於 \x0d 和 \cM。
\s 匹配任何空白字元,包括空格、製表符、換頁符等等。等價於 [ \f\n\r\t\v]。
\S 匹配任何非空白字元。等價於 [^ \f\n\r\t\v]。
\t 匹配一個製表符。等價於 \x09 和 \cI。
\v 匹配一個垂直製表符。等價於 \x0b 和 \cK。
\w 匹配包括下劃線的任何單詞字元。等價於'[A-Za-z0-9_]'。
\W 匹配任何非單詞字元。等價於 '[^A-Za-z0-9_]'。
\xn 匹配 n,其中 n 為十六進制轉義值。十六進制轉義值必須為確定的兩個數字長。例如,'\x41' 匹配 "A"。'\x041' 則等價於 '\x04' & "1"。正則表達式中可以使用 ASCII 編碼。.
\num 匹配 num,其中 num 是一個正整數。對所獲取的匹配的引用。例如,'(.)\1' 匹配兩個連續的相同字元。
\n 標識一個八進制轉義值或一個向後引用。如果 \n 之前至少 n 個獲取的子表達式,則 n 為向後引用。否則,如果 n 為八進制數字 (0-7),則 n 為一個八進制轉義值。
\nm 標識一個八進制轉義值或一個向後引用。如果 \nm 之前至少有 nm 個獲得子表達式,則 nm 為向後引用。如果 \nm 之前至少有 n 個獲取,則 n 為一個後跟文字 m 的向後引用。如果前面的條件都不滿足,若 n 和 m 均為八進制數字 (0-7),則 \nm 將匹配八進制轉義值 nm。
\nml 如果 n 為八進制數字 (0-3),且 m 和 l 均為八進制數字 (0-7),則匹配八進制轉義值 nml。
\un 匹配 n,其中 n 是一個用四個十六進制數字表示的 Unicode 字元。例如, \u00A9 匹配版權符號 (&;)。
下面看幾個例子:
"^The":表示所有以"The"開始的字元串("There","The cat"等);
"of despair$":表示所以以"of despair"結尾的字元串;
"^abc$":表示開始和結尾都是"abc"的字元串——呵呵,只有"abc"自己了;
"notice":表示任何包含"notice"的字元串。
'*','+'和'?'這三個符號,表示一個或一序列字元重復出現的次數。它們分別表示「沒有或
更多」,「一次或更多」還有「沒有或一次」。下面是幾個例子:
"ab*":表示一個字元串有一個a後面跟著零個或若干個b。("a", "ab", "abbb",……);
"ab+":表示一個字元串有一個a後面跟著至少一個b或者更多;
"ab?":表示一個字元串有一個a後面跟著零個或者一個b;
"a?b+$":表示在字元串的末尾有零個或一個a跟著一個或幾個b。
也可以使用范圍,用大括弧括起,用以表示重復次數的范圍。
"ab{2}":表示一個字元串有一個a跟著2個b("abb");
"ab{2,}":表示一個字元串有一個a跟著至少2個b;
"ab{3,5}":表示一個字元串有一個a跟著3到5個b。
請注意,你必須指定范圍的下限(如:"{0,2}"而不是"{,2}")。還有,你可能注意到了,'*','+'和
'?'相當於"{0,}","{1,}"和"{0,1}"。
還有一個'¦',表示「或」操作:
"hi¦hello":表示一個字元串里有"hi"或者"hello";
"(b¦cd)ef":表示"bef"或"cdef";
"(a¦b)*c":表示一串"a""b"混合的字元串後面跟一個"c";
'.'可以替代任何字元:
"a.[0-9]":表示一個字元串有一個"a"後面跟著一個任意字元和一個數字;
"^.{3}$":表示有任意三個字元的字元串(長度為3個字元);
方括弧表示某些字元允許在一個字元串中的某一特定位置出現:
"[ab]":表示一個字元串有一個"a"或"b"(相當於"a¦b");
"[a-d]":表示一個字元串包含小寫的'a'到'd'中的一個(相當於"a¦b¦c¦d"或者"[abcd]");
"^[a-zA-Z]":表示一個以字母開頭的字元串;
"[0-9]%":表示一個百分號前有一位的數字;
",[a-zA-Z0-9]$":表示一個字元串以一個逗號後面跟著一個字母或數字結束。
你也可以在方括弧里用'^'表示不希望出現的字元,'^'應在方括弧里的第一位。(如:"%[^a-zA-Z]%"表
示兩個百分號中不應該出現字母)。
為了逐字表達,必須在"^.$()¦*+?{\"這些字元前加上轉移字元'\'。
請注意在方括弧中,不需要轉義字元。
五種常見的 PHP 設計模式
設計模式只是為 Java™ 架構師准備的 —— 至少您可能一直這樣認為。實際上,設計模式對於每個人都非常有用。如果這些工具不是 「架構太空人」 的專利,那麼它們又是什麼?為什麼說它們在 PHP 應用程序中非常有用?本文解釋了這些問題。
設計模式 一書將設計模式引入軟體社區,該書的作者是 Erich Gamma、Richard Helm、Ralph Johnson 和 John Vlissides Design(俗稱 「四人幫」)。所介紹的設計模式背後的核心概念非常簡單。經過多年的軟體開發實踐,Gamma 等人發現了某些具有固定設計的模式,就像建築師設計房子和建築物一樣,可以為浴室的位置或廚房的構造方式開發模板。使用這些模板或者說設計模式 意味著可以更快地設計更好的建築物。同樣的概念也適用於軟體。
設計模式不僅代表著更快開發健壯軟體的有用方法,而且還提供了以友好的術語封裝大型理念的方法。例如,您可以說您正在編寫一個提供鬆散耦合的消息傳遞系統,也可以說你正在編寫名稱為觀察者 的模式。
用較小的示例展示模式的價值是非常困難的。這往往有些大材小用的意味,因為模式實際上是在大型代碼庫中發揮作用的。本文不展示大型應用程序,所以您 需要思索的是在您自己的大型應用程序中應用示例原理的方法 —— 而不是本文演示的代碼本身。這不是說您不應該在小應用程序中使用模式。很多良好的應用程序都以小應用程序為起點,逐漸發展到大型應用程序,所以沒有理由不 以此類扎實的編碼實踐為基礎。
既然您已經了解了設計模式以及它們的有用之處,現在我們來看看 PHP V5 的五種常用模式。
工廠模式
最初在設計模式 一書中,許多設計模式都鼓勵使用鬆散耦合。要理解這個概念,讓我們最好談一下許多開發人員從事大型系統的艱苦歷程。在更改一個代碼片段時,就會發生問題,系統其他部分 —— 您曾認為完全不相關的部分中也有可能出現級聯破壞。
該問題在於緊密耦合 。系統某個部分中的函數和類嚴重依賴於系統的其他部分中函數和類的行為和結構。您需要一組模式,使這些類能夠相互通信,但不希望將它們緊密綁定在一起,以避免出現聯鎖。
在大型系統中,許多代碼依賴於少數幾個關鍵類。需要更改這些類時,可能會出現困難。例如,假設您有一個從文件讀取的 User 類。您希望將其更改為從資料庫讀取的其他類,但是,所有的代碼都引用從文件讀取的原始類。這時候,使用工廠模式會很方便。
工廠模式 是一種類,它具有為您創建對象的某些方法。您可以使用工廠類創建對象,而不直接使用 new。這樣,如果您想要更改所創建的對象類型,只需更改該工廠即可。使用該工廠的所有代碼會自動更改。
清單 1 顯示工廠類的一個示列。等式的伺服器端包括兩個部分:資料庫和一組 PHP 頁面,這些頁面允許您添加反饋、請求反饋列表並獲取與特定反饋相關的文章。
清單 1. Factory1.php
<?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 介面定義用戶對象應執行什麼操作。IUser 的實現稱為 User,UserFactory 工廠類則創建 IUser 對象。此關系可以用圖 1 中的 UML 表示。
圖 1. 工廠類及其相關 IUser 介面和用戶類
如果您使用 php 解釋器在命令行上運行此代碼,將得到如下結果:
% php factory1.php
Jack
%
測試代碼會向工廠請求 User 對象,並輸出 getName 方法的結果。
有一種工廠模式的變體使用工廠方法。類中的這些公共靜態方法構造該類型的對象。如果創建此類型的對象非常重要,此方法非常有用。例如,假設您需要先 創建對象,然後設置許多屬性。此版本的工廠模式會將該進程封裝在單個位置中,這樣,不用復制復雜的初始化代碼,也不必將復制好的代碼在在代碼庫中到處粘 貼。
清單 2 顯示使用工廠方法的一個示例。
清單 2. Factory2.php
<?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 類有兩個創建對象的靜態方法。此關系可用圖 2 中的 UML 表示。
圖 2. IUser 介面和帶有工廠方法的 user 類
在命令行中運行腳本產生的結果與清單 1 的結果相同,如下所示:
% php factory2.php
Jack
%
如上所述,有時此類模式在規模較小的環境中似乎有些大材小用。不過,最好還是學習這種扎實的編碼形式,以便應用於任意規模的項目中。
單元素模式
某些應用程序資源是獨占的,因為有且只有一個此類型的資源。例如,通過資料庫句柄到資料庫的連接是獨占的。您希望在應用程序中共享資料庫句柄,因為在保持連接打開或關閉時,它是一種開銷,在獲取單個頁面的過程中更是如此。
單元素模式可以滿足此要求。如果應用程序每次包含且僅包含一個對象,那麼這個對象就是一個單元素(Singleton)。清單 3 中的代碼顯示了 PHP V5 中的一個資料庫連接單元素。
清單 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 的單個類。您不能創建自已的 DatabaseConnection,因為構造函數是專用的。但使用靜態 get 方法,您可以獲得且僅獲得一個 DatabaseConnection 對象。此代碼的 UML 如圖 3 所示。
圖 3. 資料庫連接單元素
在兩次調用間,handle 方法返回的資料庫句柄是相同的,這就是最好的證明。您可以在命令行中運行代碼來觀察這一點。
% php singleton.php
Handle = Object id #3
Handle = Object id #3
%
返回的兩個句柄是同一對象。如果您在整個應用程序中使用資料庫連接單元素,那麼就可以在任何地方重用同一句柄。
您可以使用全局變數存儲資料庫句柄,但是,該方法僅適用於較小的應用程序。在較大的應用程序中,應避免使用全局變數,並使用對象和方法訪問資源。
觀察者模式
觀察者模式為您提供了避免組件之間緊密耦合的另一種方法。該模式非常簡單:一個對象通過添加一個方法(該方法允許另一個對象,即觀察者 注冊自己)使本身變得可觀察。當可觀察的對象更改時,它會將消息發送到已注冊的觀察者。這些觀察者使用該信息執行的操作與可觀察的對象無關。結果是對象可以相互對話,而不必了解原因。
一個簡單示例是系統中的用戶列表。清單 4 中的代碼顯示一個用戶列表,添加用戶時,它將發送出一條消息。添加用戶時,通過發送消息的日誌觀察者可以觀察此列表。
清單 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 列表定義要通過怎樣的方法才能成為觀察者,UserListLogger 實現 IObserver 介面。圖 4 的 UML 中展示了這些元素。
圖 4. 可觀察的用戶列表和用戶列表事件日誌程序
如果在命令行中運行它,您將看到以下輸出:
% php observer.php
'Jack' added to user list
%
測試代碼創建 UserList,並將 UserListLogger 觀察者添加到其中。然後添加一個消費者,並將這一更改通知 UserListLogger。
認識到 UserList 不知道日誌程序將執行什麼操作很關鍵。可能存在一個或多個執行其他操作的偵聽程序。例如,您可能有一個向新用戶發送消息的觀察者,歡迎新用戶使用該系統。這種方法的價值在於 UserList 忽略所有依賴它的對象,它主要關注在列表更改時維護用戶列表並發送消息這一工作。
此模式不限於內存中的對象。它是在較大的應用程序中使用的資料庫驅動的消息查詢系統的基礎。
命令鏈模式
命令鏈 模式以鬆散耦合主題為基礎,發送消息、命令和請求,或通過一組處理程序發送任意內容。每個處理程序都會自行判斷自己能否處理請求。如果可以,該請求被處理,進程停止。您可以為系統添加或移除處理程序,而不影響其他處理程序。清單 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. 命令鏈及其相關命令
如果您運行包含某些測試代碼的腳本,則會得到以下輸出:
% php chain.php
UserCommand handling 'addUser'
MailCommand handling 'mail'
%
代碼首先創建 CommandChain 對象,並為它添加兩個命令對象的實例。然後運行兩個命令以查看誰對這些命令作出了響應。如果命令的名稱匹配 UserCommand 或 MailCommand,則代碼失敗,不發生任何操作。
為處理請求而創建可擴展的架構時,命令鏈模式很有價值,使用它可以解決許多問題。
策略模式
我們講述的最後一個設計模式是策略 模式。在此模式中,演算法是從復雜類提取的,因而可以方便地替換。例如,如果要更改搜索引擎中排列頁的方法,則策略模式是一個不錯的選擇。思考一下搜索引擎 的幾個部分 —— 一部分遍歷頁面,一部分對每頁排列,另一部分基於排列的結果排序。在復雜的示例中,這些部分都在同一個類中。通過使用策略模式,您可將排列部分放入另一個 類中,以便更改頁排列的方式,而不影響搜索引擎的其餘代碼。
作為一個較簡單的示例,清單 6 顯示了一個用戶列表類,它提供了一個根據一組即插即用的策略查找一組用戶的方法。
清單 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 );
?>
此代碼的 UML 如圖 6 所示。
圖 6. 用戶列表和用於選擇用戶的策略
UserList 類是打包名稱數組的一個包裝器。它實現 find 方法,該方法利用幾個策略之一來選擇這些名稱的子集。這些策略由 IStrategy 介面定義,該介面有兩個實現:一個隨機選擇用戶,另一個根據指定名稱選擇其後的所有名稱。運行測試代碼時,將得到以下輸出:
% php strategy.php
Array
(
[0] => Jack
[1] => Lori
[2] => Megan
)
Array
(
[0] => Andy
[1] => Megan
)
%
測試代碼為兩個策略運行同一用戶列表,並顯示結果。在第一種情況中,策略查找排列在 J 後的任何名稱,所以您將得到 Jack、Lori 和 Megan。第二個策略隨機選取名稱,每次會產生不同的結果。在這種情況下,結果為 Andy 和 Megan。
策略模式非常適合復雜數據管理系統或數據處理系統,二者在數據篩選、搜索或處理的方式方面需要較高的靈活性。
結束語
本文介紹的僅僅是 PHP 應用程序中使用的幾種最常見的設計模式。在設計模式 一書中演示了更多的設計模式。不要因架構的神秘性而放棄。模式是一種絕妙的理念,適用於任何編程語言、任何技能水平。