之前我們的一篇《兩個php常用的設計模式》介紹了php常用的設計模式,內容不夠全面,本文新增了策略模式算是對其的補充吧。面向對象的程序設計理念不僅表現在的語法規則和語言特性上,更重要的是表現了一種上設計思想。面對對象的程序本身就在強調程序設計方法。當設計一個軟件的時候,很多設計觀念被反復地用到,甚至已經成為了一種共用的規則,這些規則通常被稱為設計模式。下面要介紹的是三種最的設計模式。
策略模式(Strategy Pattern)
策略模式指的是程序中涉及決策控制的一種模式。例如,一段 PHP 代碼用來顯示一張 Html 頁面,訪問者的浏覽器可能會是 IE,也可能會是 Netscape。這時程序就需要根據客戶端浏覽器的不同顯示不同的網頁內容。
策略模式通常通過定義一個抽象的基類,然後根據情況的不同創建不同的類繼承這個基類。接下來,根據實際情況的判斷,對這個基類采用不同的方式進行繼承。
以下代碼實現了根據客戶端浏覽器的類型輸出不同文字表達式的功能。這裡,PHP 是通過 $_SERVER['HTTP_USER_AGENT'] 來獲取用戶端信息的。
<?php
//baseAgent類,抽象的基類
abstract class baseAgent
{
abstract function PrintPage();
}
//ieAgent 類,用於客戶端是 IE 時調用的類
class IEAgent extends baseAgent
{
function PrintPage()
{
return '當前浏覽器是 IE!';
}
}
//otherAgent 類,用於客戶端不是 IE 時調用的類
class otherAgent extends baseAgent
{
function PrintPage()
{
return '當前浏覽器不是 IE!';
}
}
//判斷並創建不同的對象類型,對象名為 $currPage
if(strstr($_SERVER['HTTP_USER_AGENT'], 'MSIE'))
{
$currPage = new IEAgent();
}
else
{
$currPage = new otherAgent();
}
//輸出
echo $currPage->PrintPage();
?> 上面程序在 IE 下的輸出結果如下所示。
當前浏覽器是 IE! 單例模式(Singleton Pattern)
單例模式指的是在應用程序的范圍內只對指定的類創建一個實例。例如,對於一篇公共的文檔可以允許多個用戶同時閱讀,但是僅允許一個用戶編輯,否則會出現更新不同步的問題。
單例模式包含的對象只有一個,就是單例本身。使用單例模式的類通常擁有一個私有構造耿耿數和一個私有克隆函數,確保用戶無法通過創建對象或克隆的方式對其進行實例化。除些之外,該模式中還包含一個靜態私有成員變量 $instance 與靜態方法 getInstance。 getInstance 方法負責對其本身實例化,然後將這個對象存儲在 $instance 靜態成員變量中,以確保只有一個實例被創建。
以下代碼是一個簡單的單例模式的例子,通過對單例屬性 $switch 的設置實現了對開關狀態的改變。
<?PHP
//單例模式的類 Lock
class Lock
{
//靜態屬性 $instance
static private $instance = NULL;
//一個普通的成員屬性
private $switch = 0;
//getInstance 靜態成員方法
static function getInstance()
{
//如果對象實例還沒有被創建,則創建一個新的實例
if(self::$instance == NULL)
{
self::$instance = new Lock();
}
//返回對象實例
return self::$instance;
}
//空構造函數
private function Lock()
{
}
//空克隆成員函數
private function __clone()
{
}
//設置$switch的函數,如果$switch為0則將其設置成1,否則將其設置成0
function setLock()
{
if($this->switch == 0)
$this->switch = 1;
else
$this->switch = 0;
}
//獲取$switch狀態
function getLock()
{
return $this->switch;
}
}
//調用單例,設置$switch
Lock::getInstance()->setLock();
//判斷開關狀態
if(Lock::getInstance()->getLock() == 0)
echo '開關狀態: 關';
else
echo '開關狀態: 開';
?> 運行結果如下所示。
開關狀態:開 從上面的運行結果可以看出,第一次調用 Lock::getInstance()將$switch 設置成 1,第二次調用 Lock::getInstance()時獲取的對象與第一次調用時相同。所以輸出結果為 $switch 為 1 時的結果。
工廠模式(Factory Pattern)
工廠模式是指創建一個類似於工廠的類,通過對類中成員方法的調用返回不同類型的對象。例如,一個管理系統對於訪問用戶的權限設置是不同的。對於普通用戶僅擁有一般的浏覽權限,對於管理員擁有對數據的修改和刪除權限,對於維護人員擁有訪問用戶的授權權即用等。
工廠模式通常創建一個基類,根據對象類型的不同創建不同的擴展類,而工廠類就像生產零件一件,生產出類型不同的對象。在主程序中,通過對對象的調用實現不同的功能。
以下代碼實現了一個管理系統的例子。Factory 類就是一個工廠類,類中方法 Create 用於創建類型不同的對象得到不同的權限。
<?PHP
//抽象基類User
abstract class User
{
protected $name = NULL;
//構造函數
function User($name)
{
$this->name = $name;
}
//獲取屬性 $name
function getName()
{
return $this->name;
}
//是否具有浏覽權限
function VIEwAccess()
{
return 'No';
}
//是否具有編輯權限
function EditAccess()
{
return 'No';
}
//是否具有刪除權限
function DeleteAccess()
{
return 'No';
}
//是否具有用戶管理權限
function ManageAccess()
{
return 'No';
}
}
//普通用戶
class ClIEnt extends User
{
function VIEwAccess()
{
return 'Yes';
}
}
//管理員
class Administrator extends User
{
function VIEwAccess()
{
return 'Yes';
}
function EditAccess()
{
return 'Yes';
}
function DeleteAccess()
{
return 'Yes';
}
}
//維護人員
class Supporter extends User
{
function VIEwAccess()
{
return 'Yes';
}
function EditAccess()
{
return 'Yes';
}
function DeleteAccess()
{
return 'Yes';
}
function ManageAccess()
{
return 'Yes';
}
}
//工廠類
class Factory
{
//靜態成員屬性
private static $users = array('Simon'=>'ClIEnt', 'Elaine'=>'Administrator',
'Bob'=>'Supporter');
//創建對象的成員方法
static function Create($name)
{
switch(self::$users[$name])
{
case 'ClIEnt':
return new ClIEnt($name);
case 'Administrator':
return new Administrator($name);
case 'Supporter':
return new Supporter($name);
}
}
}
//一個存放用戶名的數組
$users = array('Elaine', 'Simon', 'Bob');
//對於每個用戶分析其權限
foreach($users as $user)
{
$obj = Factory::Create($user);
echo $obj->getName().' 的權限';
echo '浏覽:'.$obj->VIEwAccess()."\n";
echo '修改:'.$obj->EditAccess()."\n";
echo '刪除:'.$obj->DeleteAccess()."\n";
echo '管理:'.$obj->ManageAccess()."\n";
}
?> 需要注意的是工廠模式通常與策略模式結合使用,工廠模式通過對實例情況的判斷正確的策略創建出合適的對象。