1. 程式人生 > >淺談PHP面向物件程式設計(九)

淺談PHP面向物件程式設計(九)

9.0 設計模式


  在編寫程式時經常會遇到一此典型的問題或需要完成某種特定需求,設計模式就是針對這些問題和需求,在大量的實踐中總結和理論化之後優選的程式碼結構程式設計風格,以及解決問題的思考方式。

設計模式就像是經典的棋譜。不同的棋局,使用不同的棋諧,免得自己再去思考和模索。本節將針對PHP應用程式中最常用的兩種設計模式進行詳細講解。

9.1 單例模式


   單例模式是PHP中的一種設計模式,它是指在設計一個類時,需要保證在整個程式執行期間針對該類只存在一個例項物件。

就像世界上只有一個月亮,假設現在要設計一個類表示月亮,該類只能有一個例項物件,否則就違背了事實。

在講解單例設計模式之前,通過一個案例來演示在什麼情況時需要使用單例模式,如例9-23 所示

例9-2

 

複製程式碼
 1 <?php
 2      class dbHelper{
 3 private $conn = null;  4 public function __construct(){  5 //開啟一個到 MySQL 伺服器的連線  6 $this->conn = mysql_connect("localhost","root","");  7 echo "得到一個conn<br/>";  8  }  9  } 10 $db1 = new dbHelper(); 11 $db2 = new dbHelper(); 12 if($db1 === $db2){ 13 echo "一個物件<br/>"; 14 } else { 15 echo "兩個物件<br/>"; 16  } 17 ?>
複製程式碼

 

執行結果

 

得到一個conn

得到一個conn

兩個物件

 

從上例中可以看出,例項化類dbHelper的兩個物件請求的資料庫連線是兩個不同的連線,而在實際開發中,有時會有這樣的需求,

在一次HTTP 請求中,保證某個類的物件例項只能有一個。這樣可以節省資源開銷,此時可以使用單例模式。

      單例模式(Singleton)用於為一個類生成一個唯一的物件。(請記住名詞    “”三私一公“”)

私有靜態屬性

私有構造方法

私有克隆方法

公有靜態呼叫隊象方法 

將上面的dbHelper 類使用單例模式來實現,如例9-24所示

例9-24

複製程式碼
<?php
    class dbHelper{
        private static $instance = null;//定義一個私有的靜態屬性$instance //宣告一個構造方法 private function __construct(){ $this->conn = mysql_connect("localhost","root",""); echo "得到一個conn<br/>"; } //只有通過這個方法才能返回本類的物件,該方法是靜態方法 public static function getInstance(){ //如果本類中的$instance為空,說明它還沒有被例項化過 if(self::$instance == null){ self::$instance = new self();//例項化本類物件  } return self::$instance;//返回本類的物件  } //阻止使用者複製物件例項 public function __clone(){ } } $db1 = dbHelper::getInstance(); $db2 = dbHelper::getInstance(); if($db1 === $db2){ echo "同一個物件"; }else{ echo "不是同一個物件"; } ?>
複製程式碼

 

執行結果

得到一個conn

同一個物件

 

在上例中,dbHelper類的構造方法使用了private 關鍵字進行了修飾,即不能在類定義之外使用new來建立物件。

如此一來就只能通過類 名直接呼叫getinstance0靜態方法來建立物件。在第3行程式碼聲明瞭一個私有的靜態屬性$instance.

將例項化的物件賦值給它,再判斷該屬性,如果已經有值,就直接返回,如果其值為null, 就先例項化物件,這樣就能保證dbHelper類只能被例項化一次。

最後增加了一個私有的魔術方法_ clone0. 用於防止使用者通過clone方法複製物件。

 

 9.2 工廠模式


 

工廠模式的作用就是“生產”物件。工廠方法的引數是要生成物件的類名。

為了方便理解工廠模式的作用,接下來通過一個案例來演示如何使用工廠模式獲取MySQL和sQLite的驅動物件。

首先在根目錄下建立MySQLphp檔案。示例程式碼如下:

複製程式碼
1 <?php
2     class  MySQL{ 3 4 //操作SQL的驅動類 5 6 }
複製程式碼

然後在根目錄下建立SQLite.php檔案。示例程式碼如下:

複製程式碼
1 <?php
2 class SQLite{
3 4 //操作SQLite的驅動類 5 6 }
複製程式碼

 

 最後定義一個工廠方法來獲取各驅動物件,程式碼如例9-25所示

例9-25

複製程式碼
 1 <?php
 2      header('Content-Type: textml;charset=utf-8');
 3 class Db{  4 //工廠方法  5 public static function factory($type){  6 if (include_once $type . '.php') {  7 $classname = $type;  8 return new $classname();  9 } else { 10 echo "出錯了!"; 11  } 12  } 13  } 14 //獲取MySQL驅動物件 15 $mysql = Db::factory('MySQL'); 16 //獲取SQLite驅動物件 17 $sqlite = Db::factory('SQLite'); 18 var_dump($mysql); 19 var_dump($sqlite); 20 ?> 
複製程式碼

 執行結果

object (MySQL) [1]

object (SQLite) [2]

 

上例中,第5行程式碼定義了一個靜態方法factor(), 這就是工廠方法,該方法的引數為類名。

第6- 11行程式碼用於判斷類名與引數是否相同,如果相同則建立該類的物件,否則輸出“出錯了!”。

第15 17行程式碼分別呼叫factory()方法獲取對應的驅動物件。

從執行結果可以看出,工廠方法成功地建立了兩個驅動類物件。