設計模式(Design pattern)是一套被反覆使用、多數人知曉的、通過分類編目的、代碼設計經驗的總結。使用設計模式是爲了可重用代碼、讓代碼更容易被他人理解、保證代碼可靠性。 毫無疑問,設計模式於己於他人於系統都是多贏的;設計模式使代碼編制真正工程化;設計模式是軟件工程的基石脈絡,如同大廈的結構同樣。php
本系列文章不會直接上代碼直接進行解釋,我一直認爲帶着問題來學習是效率最高的學習方式。html
本系列文章不會有演示截圖,你爲何不敲一遍加深印象呢,另外說不定個人代碼有錯。算法
我所寫的文章只是我對於編程的理解,若是有錯誤但願可以獲得指正以避免誤人子弟。編程
步子邁大了容易扯到蛋,若是在沒有熟悉 OOP 編程思想前就開始學習設計模式,我感受會有兩種可能,不是「扯蛋」,就是「拉跨」。設計模式
固然上面的話是一句玩笑話,學習設計模式能夠有效的提升咱們的代碼質量與深刻的理解 OOP 編程理念,如可是果在沒有紮實的功底(至少要要理解了抽象、接口、多態)前就開始學習設計模式會越學越難,腦子愈來愈渾,那就真變成了從入門到放棄了,由於你的思惟尚未真正的走進 OOP(單身狗表示徹底沒法面向對象^_^)。數據結構
對於設計模式的不理解我感受主要分爲兩種,一種是不知道怎麼實現的,緣由就是如上所述,另一種是不知道爲何要這麼用的,其實沒有必要糾結於爲何這麼用,這麼用了有啥做用,設計模式不過是與算法同樣只是爲了實現某個特定環境下可使用的一種更好的選擇。函數
更好一點的例子就是當咱們對一些數據進行排序的時候,咱們首先想到就是那幾個排序算法同樣,當咱們打着打着代碼忽然靈光一閃,好像這個地方用這個設計模式寫起來會輕鬆一點。學習
當碰到不懂得地方,思考一下,想不通,就出去走走,把這個東西放下來,反正就算看到次日凌晨也也是無用的,當真正遇到問題的時候,靈光一閃這個東西能夠這麼寫,而後去實踐,這就是個人學習之道。還有就是儘可能去學實例,而不是去死扣概念,當你真正用起來了,你也就差很少懂了,算法與數據結構亦是如此。this
本系列文章儘可能以推導的形式來進行書寫,而不是以現成的代碼來進行講解,讓讀者知道設計模式是怎麼來的也就是如何演化出來的,但願各位可以喜歡。另外本系列的文章並不會提供運行界面的截圖,若是想看看結果是否正確,爲何不本身試試呢?編碼
開頭引用的話來自於百度百科,我相信不少剛剛開始接觸編程的人都會犯暈,由於全部人都不喜歡被學術化的文字,咱們以設計模式中較爲經常使用的策略模式來進行演示,當咱們編寫一個廣告模塊的時候,公司給的要求是根據訪問者的性別來進行顯示廣告以提升轉化率,那咱們應該怎麼寫呢?
首先咱們想到的是在每個廣告位上面都使用 if 判斷來判斷訪客的性別,這樣就可以解決這樣的需求,那麼咱們的每個廣告代碼的代碼塊多是這個樣子的:
判斷 男 or 女{ 若是是男的就是男人的廣告 }else{ 顯示女人的廣告 }
既然僞代碼想好了,那麼咱們就能夠着手進行開發了,而後咱們在 if 代碼塊中添加各自的家在廣告代碼,因而就變成了下面的樣子:
if ($_GET['sex'] == 'man') { echo '外星人大減價如今購買當即送電競瑞文皮膚'; }else{ echo '卡西歐美顏相機不要錢免費送!'; }
可是這是屬於一種硬編碼的編程方式,一旦咱們增長了某種需求,要求其年齡大於23歲顯示什麼樣的廣告,那麼咱們就不得不在每個 if 判斷處再加上新的判斷條件,這樣的設計就是不合理的,爲了提升可讀性與可維護性,咱們會考慮創建兩個不一樣的類來對兩個廣告類來對其進行管理。因而代碼變成了下面的樣子。
//index.php include 'GenderAD.php'; include 'ManAD.php'; if ($_GET['sex'] == 'man') { $ad = new ManAD(); }else{ $ad = new GenderAD(); } $ad->show(); //GenderAD.php class GenderAD { public algorithm(){ echo '卡西歐美顏相機不要錢免費送!'; } } //ManAD.php class ManAD{ public algorithm(){ echo '外星人大減價如今購買當即送電競瑞文皮膚'; } }
algorithm 英[ˈælgərɪðəm] 美[ˈælɡəˌrɪðəm] n. 演算法; 運算法則; 計算程序;
其實到了這一步就已經算是一個簡單的策略模式了,由於他已經具備策略的特質了,只不過還不夠完善,若是說這不算什麼的話我也沒有辦法,由於全部的設計模式其實都是思惟模式與表現形式罷了,就像上面的引用中提到的同樣,設計模式只不過是爲了可以讓代碼能夠重用,更容易他讓人理解,由於你的代碼並非你一我的在維護,那麼問題來了,只是簡單的對其進行封裝真的就提升代碼的可維護性了麼,其實並無,咱們尚未將 OOP 的設計概念發揮到極致。
通過分析咱們發現其實 ManAD類和 GenderAD最終都要進行顯示,他們的方法的顯示方法都是 show,若是是你一我的在開發那麼沒有什麼問題,但是如果兩我的開發呢,大家能夠直接能夠對話的方式進行溝通,協定好都是 show方法來顯示,但是爲何不用更工程化的方式來實現呢?
咱們可使用接口來實現這一目的,若是對接口還不瞭解,能夠去查閱一下資料,很快你就可以明白,在本文結束後我會在下方標註出參考範例。
咱們能夠新建一個接口來對這些策略進行控制。
interface ADinterface{ public function algorithm(); } class ManAD implements ADInterface { public function algorithm(){ echo '外星人大減價如今購買當即送電競瑞文皮膚'; } } class GenderAD implements ADInterface { public function algorithm(){ echo '卡西歐美顏相機不要錢免費送!'; } }
這樣一來廣告策略必須遵循這個接口進行開發,就保證了全部策略類都須要實現 show 方法。
到目前爲止,策略模式已經相對的完善了,可是仍是不夠完美,由於代碼依舊並非很 OOP,咱們其實還能夠更進一步,讓他更 OOP,咱們能夠對那些策略外面套一個殼子,給外面一個選擇器。
class StrategySelect { //具體策略對象 private $strategyInstance; //構造函數 public function __construct($instance) { $this->strategyInstance = $instance; } public function algorithm($strategy) { return $this->strategyInstance->algorithm(); } }
咱們經過構造函數接收到具體的執行策略,而後使用algorithm()執行相對應的策略。
<?php interface ADinterface{ public function algorithm(); } class StrategySelect { //具體策略對象 private $strategyInstance; //構造函數 public function __construct($instance) { $this->strategyInstance = $instance; } public function algorithm() { return $this->strategyInstance->algorithm(); } } class ManAD implements ADInterface { public function algorithm(){ echo '外星人大減價如今購買當即送電競瑞文皮膚'; } } class GenderAD implements ADInterface { public function algorithm(){ echo '卡西歐相機免費贈送啦'; } } header("Content-type:text/html;charset=utf-8"); if ($_GET['sex'] == 'man') { $stratey = new StrategySelect(new ManAD()); $stratey->algorithm(); }else{ $stratey = new StrategySelect(new GenderAD()); $stratey->algorithm(); }
Strategy其實算是一個策略選擇器,當知足必定條件的時候,咱們經過這個策略選測器來進行選擇相對應的策略。這樣一來更符合邏輯。是否是很 OOP?
若是有什麼不懂得能夠在評論區進行留言,有時間我會一一答覆,若是發現本文中有什麼錯誤請指出,我也懼怕誤人子弟,特別是概念上的東西,在最後StrategySelect類的講解上我依舊感受寫的很模糊,有些差強人意。
個人博客網址:www.aircrayon.xyz,有興趣的朋友能夠去看看,不過上面的東西好久沒有更新了,並且有的博文內容不全。
《Leaning PHP Design Patterns》 William Sanders 著 蘇金國 王宇飛等譯
《PHP之道》
《PHP大話設計模式》 Rango(韓天峯) 錄製者 慕課網視頻教程