1. 程式人生 > >PHP設計模式理解

PHP設計模式理解

   一聽別人用了什麼什麼設計模式,總感覺多麼高大上似得。其實仔細理解起來,會發現你自己平時敲程式碼的時候有很多的思路原則,也正式某些設計模式中所要達到的思想。無非是前人開發中碰到的問題時,不利於繼續開發維護,從而想出的最佳解決方案,久而久之便形成了公認的固有寫程式碼的開發模式。

個人感覺,其目的大多是為了 可維護性,可擴充套件性,可複用性而服務,一切的目的則是減少專案開發中的成本與困難度。

 下邊是自己的一些關於設計模式的通俗的理解,比較山野 隨意化偷笑,希望能從另一個方面幫助理解。

建立型模式,共五種:工廠方法模式、抽象工廠模式、單例模式、建造者模式、原型模式。

結構型模式,共七種:

介面卡模式、裝飾器模式、代理模式、外觀模式、橋接模式、組合模式、享元模式。

行為型模式,共十一種:策略模式、模板方法模式、觀察者模式、迭代子模式、責任鏈模式、命令模式、備忘錄模式、狀態模式、訪問者模式、中介者模,註冊模式

本文先涉及如上綠色10種設計模式。

1.單例模式【建立型】:使某個類的物件僅允許建立一次

單例模式顧名思義,就是隻有一個例項。作為物件的建立模式, 單例模式確保某一個類只有一個例項,而且自行例項化並向整個系統提供這個例項。

單例模式的要點有三個:

  1. 一是某個類只能有一個例項;
  2. 二是它必須自行建立這個例項;
  3. 三是它必須自行向整個系統提供這個例項。

為什麼要使用PHP單例模式

  1. 1. php的應用主要在於資料庫應用, 一個應用中會存在大量的資料庫操作, 在使用面向物件的方式開發時, 如果使用單例模式, 則可以避免大量的new 操作消耗的資源,還可以減少資料庫連線這樣就不容易出現too many connections情況。

  2. 2. 如果系統中需要有一個類來全域性控制某些配置資訊, 那麼使用單例式可以很方便的實現. 這個可以參看zend Framework的FrontController部分。

  3. 3. 在一次頁面請求中, 便於進行除錯, 因為所有的程式碼(例如資料庫操作類db)都集中在一個類中, 我們可以在類中設定鉤子, 輸出日誌,從而避免到處var_dump, echo。

2.工廠模式【建立型】:工廠方法或者類生成物件,而不是在服務端中直接 NEW,在客戶端端NEW

    抽象工廠類  -》多個具體工廠類-》一個具體產品類      然後客戶端多個new呼叫即可

    對於修改是封閉的,對於擴充套件是開放的

    想新增新介面,服務端新加具體工廠類,具體產品類,客戶端new就行了【實現了服務端不修改,可擴充套件】

3.簡單工廠方法【建立型】,【就是減少NEW次數的】

    抽象工廠類-》多個具體工廠類-》common類(含引數)        然後客戶端new一個common類傳參即可

    想新增新介面,服務端新加具體工廠類,common中修改新增,客戶端還是new common類,只是換個引數【違背了服務端不修改原則】

    比如自己寫的API,呼叫相同類的不同引數,獲得不同方法的結果值,但是破壞了 對於修改是封閉的,對於擴充套件是開放的, API這種方式想要拓展,需要改入口函式的,

工廠模式區別.md 【本質就是,簡單工廠模式,遵循不修改,可擴充套件。讓客戶端省事了,減少了new的次數傳引數就行】

4.註冊模式【行為型】:全域性共享和交換物件

單例模式保證了一個類中只有一個例項被全域性訪問,當你有一組全域性物件被全域性訪問時可能就需要用到註冊者模式 (registry)

它 提供了在程式中有條理的存放並管理物件 (object)一種解決方案。一個“註冊模式”應該提供get() 和 set()方法來儲存和取得物件(用一些屬性key)而且也應該提供一個isValid()方法來確定一個給定的屬 性是否已經設定。 

5.觀察者模式【行為型】:【就是遍歷陣列實現一次監聽 】

    例項化時先把新物件add成員屬性的陣列,然後執行一個觸發器方法,用來遍歷剛剛那個陣列 

 當一個物件發生改變時, 依賴他的物件全部會收到通知,並自動進行相應操作

  缺點:一個事件發生後,要執行一連串更新操作。傳統的程式設計方式:時間程式碼後邊直接加入處理邏輯,當更新的邏輯增多後,程式碼變得難以維護。耦合度高,增加新邏輯需要修改事件 主題程式碼

6.責任鏈模式【行為型】:【就是一層一層new,根據責任權來if判斷是否本類處理 】

    特點:有兩個成員屬性,power權的大小,top下一級別權的類名,

            上來先if判斷傳入的權是否大於奔雷的power,大於的話else例項化下一級別的類,同上操作

    缺點:當權值較大時,必須把權小的一步一步都例項化(類似於從村,鎮,鄉,市..一步一步辦事情,大事得高階部門辦)

7.策略模式【行為型【和簡單工廠類似,就是switch case 部分換成 虛擬的類,用變數動態化型別從而實現各個拓展功能】

策略模式定義了一系列的演算法,並將每一個演算法封裝起來,而且使它們還可以相互替換。策略模式讓演算法獨立於使用它的客戶而獨立變化,即封裝變化的演算法。

    關鍵:$this->classname = $classname;($classname是使用者例項化時傳過來)

               $this->classname->common_method($cal1,$cal2);(引數也是傳過的 ,紅字是關鍵,從原來每個得寫出來變為變數,與簡單工廠的區別 也再此)

8.裝飾器模式【結構型

裝飾者模式就是不修改原類程式碼和繼承的情況下動態擴充套件類的功能。傳統的程式設計模式都是子類繼承父類實現方法過載,使用裝飾器模式,只需新增一個新的裝飾器物件,更加靈活,避免類數量和層次過多。

    笨辦法:寫一個基礎功能,然後想要裝飾拓展此功能,一層一層繼承,往上裝飾,缺點,順序侷限,繼承太多

    新方法:此模式的誕生,本質是把該物件的資源,作為新物件例項化的構造引數,把上一層物件扔進來,在新類裡處理,retun出去,後頭同此方法繼續,從而達到層層裝飾的模式

    $baseobj = new obj();

    $obj = new obja(  new objb(  new objc()  ) );//迴圈巢狀,一層一層把修飾的東西積累

    $obj->common_method()//通過呼叫相同的繼承父類方法,實現載入

9.介面卡模式【結構型】(接過來舊的,轉換成新的格式傳給適用的物件)

    原來的類滿足不了所有的介面格式,用一個adapter,來繼承這個類,然後在介面卡類裡對資料處理然後返回

    就像日本110V的電壓,來的中國220V充電,就得用一個介面卡來轉接,道理一樣。

10.橋接模式【結構型

本質也是要把其中一個物件傳入類中,賦值給該類成員屬性儲存起來,然後再在公共方法呼叫加上自己的程式並呼叫

把M * N 的類的結構變成 N + M各類,減少了類的書寫

比如 跑,跳,飛   和 小名, 小紅, 小剛  正常得寫9各類,而橋接只寫3+3個類

簡單工廠模式與策略模式區別:

當時我在說明策略模式與工廠模式區別的時候舉了一個例子。

說你要去買件衣服,給你50塊錢,策略模式的做法就是去京東、噹噹、淘寶、卓越等網上去看,然後決定要買那一件。而工廠模式的做法確實,告訴系統我需要用50塊錢買件衣服,到底他去噹噹、淘寶、京東、卓越你不關心,你只需要50塊錢的一件衣服。淘寶mm一語道出工廠相當於黑盒子,策略相當於白盒子。

簡單工廠模式:創造性

策略模式:行為性


//工廠模式
class ProductFactory {
public static function create($num) {
switch($num) {
case 1:
return new ProductA();
case 2:
return new ProductB();
}
return null;
}
}
//傳遞不同的引數獲取不同的物件
$obj=ProductFactory::create(1);
$obj->getName(); //這是A商品
$obj=ProductFactory::create(2);
$obj->getName(); //這是B商品
 
//=======策略模式
<?php
header('content-type:text/html;charset=utf-8');
interface IStrategy {
function ontheway();
}
class Walk implements IStrategy {
public function ontheway() {
echo '走著去<br>';
}
}
class Bick implements IStrategy {
public function ontheway() {
echo '騎自行車去<br>';
}
}
class Bus implements IStrategy {
public function ontheway() {
echo '坐巴士去<br>';
}
}
//策略模式,傳遞不同的引數,呼叫不同的策略
class Strategy{
public function getWay(IStrategy $obj) {
$obj->ontheway();
}
}
$obj=new Strategy();
$obj->getWay(new Walk); //走著去
$obj->getWay(new Bick); //騎自行車去
$obj->getWay(new Bus); //坐巴士去