PHP Pattern Singleton 持續使用 同一個 類別 產生 的 物件

PHP Pattern Singleton, keep use an object of a class

90
當我們創造一個類別時,有時候會希望在不同的地方都使用同一個物件就好,
不要每個地方都產生一個,造成資源的浪費,下面先舉個例子
假設每個學生都可以擁有一支手電筒,而且學生可以打開手電筒,跟關閉手電筒
所以我先產生一個手電筒的類別,還有一個學生的類別

class Light //手電筒
{
private $Name; //手電筒的名稱
public function __construct($inputName)
{
echo "Create a Light Object";
$this->Name = $inputName;
}
public function turnOn()
{
echo "Light \"$this->Name\" is TURN ON now";
}
public function turnOff()
{
echo "Light \"$this->Name\" is TURN OFF now";
}
}



include_once("Light.php");
class Student//學生
{
private $Name; //學生姓名
private $MyLight;
public function __construct($inputName)
{
echo "Create a Student Object names $inputName";
$this->Name = $inputName;
echo "Create a Lignt for this student use";
$this->MyLight = new Light($inputName."'s Light");
}
public function turnOnMyLight()
{
$this->MyLight->turnOn();
}
public function turnOffMyLight()
{
$this->MyLight->turnOff();
}
public function goPlay()
{
echo "do nothing only play";
}
}

接著我們開始使用學生這個類別,創造一個物件,然後讓學生打開他的手電筒

include_once("Student.php");
$MyStudent = new Student("Michael");
$MyStudent->turnOnMyLight();
/*
** 這時候會輸出一些訊息
** Create a Student Object names Michael
** Create a Lignt for this student use
** Create a Light Object
** Light "Michael's Light" is TURN ON now
*/
//從訊息看到,我們成功的讓這個學生擁有一個手電筒,並且打開他

這樣的作法是,產生學生的物件時,一並產生手電筒的物件,之後當學生需要使用時
就直接把產生好的手電筒拿出來使用。


但問題來了


有時候學生可能要做的事情還很多,例如上面我還多寫了一個goPlay的函式
可能這個學生有80%的機率都在玩,20%的機率才用到手電筒
那一開始就先產生好的手電筒,就有80%的機率浪費掉了,因為他根本用不到


那有沒有辦法在需要使用手電筒的時候,再產生,而當下一次又要使用時,依然可以使用?
當然可以~其實只要稍微改寫一下一開始Student的類別就可以做到

include_once("Light.php");
class Student//學生
{
private $Name; //學生姓名
private $MyLight;
public function __construct($inputName)
{
echo "Create a Student Object names $inputName";
$this->Name = $inputName;

//為了區別,我這裡的Code還是留著,只是註解掉
//echo "Create a Lignt for this student use";
//$this->MyLight = new Light($inputName."'s Light");
}
private function createLight() //多一個產生Light的函式
{
//把建構子註解掉的Code拿過來放在這邊
echo "Create a Lignt for this student use";
$this->MyLight = new Light($this->Name."'s Light"); //$inputName 要改成 $this->Name
}
public function turnOnMyLight()
{
if(!isset($this->MyLight)) //如果並沒有MyLight,就先產生
{
$this->createLight();
}
$this->MyLight->turnOn();
}
public function turnOffMyLight()
{
if(!isset($this->MyLight)) //如果並沒有MyLight,就先產生
{
$this->createLight();
}
$this->MyLight->turnOff();
}
public function goPlay()
{
echo "do nothing only play";
}
}

上面的的寫法跟第一次寫的差別在於,沒有在一開始的建構子就產生手電筒
有用到的時候在產生,而且每當要使用時,只需要透過簡單的判斷「有沒有產生過」
沒有產生過就直接創造一個來使用,這樣80%在玩樂的學生,就不會浪費還需要產生手電筒的資源,而少數學生需要手電筒時,依然可以使用


以上的方法,是寫在Student這邊
那要介紹的Singleton的概念也是如此,只是在Light那個類別就把這個概念實作完成


改寫過後的Light會變這樣

class Light //手電筒
{
private $Name; //手電筒的名稱
//需要一個屬於這個class唯一的變數來存下到時候產生的物件
private static $instance;
public function __construct($inputName)
{
echo "Create a Light Object";
$this->Name = $inputName;
}
public static function Singleton($inputName) //多了一個Singleton的函數
{
//首先先判斷有沒有產生過這個物件,有的話就直接回傳使用,沒有的話再產生
if (!isset(self::$instance)) {
$className = __CLASS__;
self::$instance = new $className($inputName);
}
return self::$instance;
}
public function turnOn()
{
echo "Light \"$this->Name\" is TURN ON now";
}
public function turnOff()
{
echo "Light \"$this->Name\" is TURN OFF now";
}
}

而Student使用Light的方式也要改變

include_once("Light.php");
class Student//學生
{
private $Name; //學生姓名
//private $MyLight; //這裡這個MyLight也不需要了
public function __construct($inputName)
{
echo "Create a Student Object names $inputName";
$this->Name = $inputName;
}
/* 這整個函式不再需要了
private function createLight()
{
//把建構子註解掉的Code拿過來放在這邊
echo "Create a Lignt for this student use";
$this->MyLight = new Light($inputName."'s Light");
}*/
public function turnOnMyLight()
{
//改用Singleton的方式產生物件,不再用new
$tempMyLight = Light::Singleton($this->Name."'s Light");
$tempMyLight->turnOn();
}
public function turnOffMyLight()
{
//改用Singleton的方式產生物件,不再用new
$tempMyLight = Light::Singleton($this->Name."'s Light");
$tempMyLight->turnOff();
}
public function goPlay()
{
echo "do nothing only play";
}
}

接著我們使用這個Student試試看

include_once("Student.php");
$MyStudent = new Student("Michael");
$MyStudent->turnOnMyLight(); //先打開
$MyStudent->turnOffMyLight(); //再關上
/*
** 這時候會輸出一些訊息
** Create a Student Object names Michael
** Create a Light Object
** Light "Michael's Light" is TURN ON now
** Light "Michael's Light" is TURN OFF now
*/
//從訊息看到,Create a Light Object只出現一次
//並沒有因為我呼叫turnOnMyLight及turnOffMyLight之後就出現兩次
//而且我也不需要在Student那邊特意存下MyLight

上面介紹的概念就是Singleton,目的就是希望有些物件重複使用不要重複產生物件
而且是要用到再產生,盡量讓使用上方便一點。
以上是基本的使用方式,希望這樣的介紹會讓你更了解Singleton!


參考資料:


喜歡我們的文章嗎
給一個讚吧~^^
本站聲明
目前偵測到您現在處於未登入的狀況中 若在此狀態進行收藏很有可能導致資料遺失或錯誤 建議先行登入後重新執行步驟,不僅能保障收藏資料也能獲得最新的資訊唷! kikinote小精靈關心您!
不再顯示此視窗