標籤:

什麼是php單例模式?


其實單例模式,說白了就是說一個類只能實例化一次。但是我們如何在這個實例化一次上面做文章呢。其實有個突破口就是__construct()這個魔術方法。這個方法就代表著如果類實例化的時候,就會自動執行這個方法。然後如果我把這個方法變成保護或者私有的,會是什麼效果呢。

&

然後執行以下,就會出現這個情況。

這樣的話,就不能實例化了。這樣就保證不能隨便讓人給實例化了。

但是既然這樣的話,我們應該怎麼實現實例化呢。就是這樣:

&

這樣的話。實例的話,就能出現了。我們看一下:

但是說了這麼多,我還是沒說到重點。下面重點來了,只要我們再使用一個關鍵字(static)就好了。鐺鐺鐺鐺:

&";
echo $test2 == $test3 ? "true" : "false";
echo "&";
echo $test1 == $test3 ? "true" : "false";
?&>

看一下結果:

這樣的話就能實現php單例的效果了。

單例的話,最長用在需要只使用這一個類,而不是會有多個類。

打個比方。比如現在有個config類,這個類主要是存儲這個項目的配置信息。如果說這個類能實例化多次的話,那麼如果在代碼運行中對配置進行了修改,那麼你怎麼知道是在哪個配置類中進行了修改了呢。這個時候的話使用單例模式,就避免了情況的發生,所有對於配置文件的改變都是基於這個類的實例進行修改的。而不會出現因為多個類的實例化,操作對於操作的改變沒有進行實時的更新。而且,實例多個類庫,佔用內存也會非常的厲害,這樣只實例化一次。是不是好處多多呢。


來,帶你裝B帶你飛;

/*
單例設計模式 (單態)
定義: 一個類 只能允許有 一個對象存在.
1.不讓進: 使類不能被實例化
2.留後門: 設置靜態方法
3.給對象: 在靜態方法里實例化該類
4.判初夜: 判斷是否是 第一次產生該類的對象
5.設靜態: 靜態方法里 要使用靜態屬性
*/

/*//1.不讓進: 使類不能被實例化-----------------
class Test
{
// 設置 一個封裝的構造方法
private function __construct()
{
//佔位, 我就是不讓你NEW我~~~
}
}*/

/*//2.留後門: 設置靜態方法--------------------
class Test
{
// 設置 一個封裝的構造方法
private function __construct()
{
//佔位, 我就是不讓你NEW我~~~
}
//後門
public static function getObject()
{
echo "啊,我是後門,進吧!&";
}
}*/

/*//3.給對象: 在靜態方法里實例化該類------------------
class Test
{
// 設置 一個封裝的構造方法
private function __construct()
{
//佔位, 我就是不讓你NEW我~~~
}
//後門
public static function getObject()
{
echo "啊,我是後門,進吧!&";
return new self();//實例化一個對象給你
}
}*/

/*//4.判初夜: 判斷是否是 第一次產生該類的對象------------------
class Test
{
private $obj = null;//屬性值為對象,默認為null
// 設置 一個封裝的構造方法
private function __construct()
{
//佔位, 我就是不讓你NEW我~~~
}
//後門
public static function getObject()
{
echo "啊,我是後門,進吧!&";
if ($this-&>obj === null) {
$this-&>obj = new self();//實例化一個對象
}
//返回的屬性 其實就是本對象
return $this-&>obj;
}
}*/

//5.設靜態: 靜態方法里 要使用靜態屬性------------------
class Test
{
private static $obj = null;//屬性值為對象,默認為null
// 設置 一個封裝的構造方法
private function __construct()
{
//佔位, 我就是不讓你NEW我~~~
}
//後門
public static function getObject()
{
echo "啊,我是後門,進吧!&";
if (self::$obj === null) {
self::$obj = new self();//實例化一個對象
}
//返回的屬性 其實就是本對象
return self::$obj;
}
}

/*Test::getObject();//使用靜態方法訪問該類里的方法
exit;*/

$t1 = Test::getObject();
$t2 = Test::getObject();
$t3 = Test::getObject();
$t4 = Test::getObject();
$t5 = Test::getObject();
$t6 = Test::getObject();
$t7 = Test::getObject();
$t8 = Test::getObject();

//判斷 兩個對象 是否是同一個對象
if ($t1 === $t6) {
echo "哦, Yes! 是同一個實例&";
} else {
echo "哦, No! 不是同一個實例&";
}

第五步是成品,前面4步都是一步一步的推的!


static function getInstance($class, $param = array())
{
if (!isset($obj[$class])) {
$obj[$class] = new $class($param);
}
return $obj[$class];
}
在實例化一個類時,先判斷是否有這個類的實例,如果有就不實例化,反之就實例化一個


厲害 樓主無敵


Talk is cheap,show you my code.

最簡單的PHP單例模式的類:

class TestInstance
{
public static $_instance = null;

//為了防止外部new這個類,所以構造方法用protected,這是單例模式的關鍵之處
protected function __Construct()
{
echo "Instance,Instance,Instance..........";
}

//用一個靜態變數存儲類的實例,只有第一次實例化的時候才賦值,以後都直接給出靜態實例
public static function getInstance()
{
if(!isset(self::$_instance)){
self::$_instance = new static();
}

return self::$_instance;
}
}

使用:

$aa = TestInstance::getInstance();
$aa-&>xx();

$bb = TestInstance::getInstance();
$bb-&>xx()

關鍵的說明已經在代碼注釋中了,明白這兩點就懂了。

參考鏈接:寫一個PHP單例模式的類


推薦閱讀:

LNMP 教程有哪些值得推薦?
php為什麼要設計成單線程語言?
如何評價知乎幾乎所有PHP相關問題中都出現「PHP是世界上最好的語言」的無關回答的現象?
在日常的網頁開發中,apache的角色是什麼樣的?(如果並不需要將數據上載伺服器的話),為什麼一定要用
PHP初學者應該選擇哪個版本的ThinkPHP?

TAG:PHP |