最近無意中看到一些對(duì)·單例模式·介紹的資料,有以下幾個(gè)疑問:
假設(shè)我的項(xiàng)目中有很多功能, 我的理解是 "用戶每操作一下, 都會(huì)產(chǎn)生一個(gè)進(jìn)程, 或者是一個(gè)進(jìn)程中制作一次請(qǐng)求--相應(yīng)操作, 然后當(dāng)前操作在服務(wù)器運(yùn)行完成并返回響應(yīng), 則進(jìn)程結(jié)束, 這樣的話, 假設(shè)你有個(gè)單例類是Log類, 用來記錄日志, 那么本次進(jìn)程結(jié)束后, 進(jìn)程中的單例自然也就被銷毀了, 另外一次操作的話, 這次操作會(huì)再次生成新的Log實(shí)例"
還有資料說:"濫用單例將帶來一些負(fù)面問題,如為了節(jié)省資源將數(shù)據(jù)庫連接池對(duì)象設(shè)計(jì)為的單例類,可能會(huì)導(dǎo)致共享連接池對(duì)象的程序過多而出現(xiàn)連接池溢出"
<?php
//final防止類被繼承
final class DBHelper{
//初始化實(shí)例 含義:$install = new DBHelper()...
private static $instance=null;
//構(gòu)造器私有,防止類外部實(shí)例化
private function __construct(){
//連接數(shù)據(jù)庫操作
}
//獲取實(shí)例
public static function getInstance(){
if(!(self::$instance instanceof self)){
self::$instance=new self;
}
return self::$instance;
}
//防止實(shí)例被克隆
private function __clone(){
}
}
?>
1.單例即類只有一個(gè)示例,如果繼承,那就會(huì)產(chǎn)生多個(gè)實(shí)例,此時(shí)已經(jīng)不是單例了。
2.理解差不多沒錯(cuò),單例解決的是同一個(gè)請(qǐng)求內(nèi),多處使用同一個(gè)類的問題。。比如一個(gè)請(qǐng)求內(nèi),可能要查十次數(shù)據(jù)庫,單例就是保證這十次使用的是同一個(gè)數(shù)據(jù)庫連接實(shí)例,而不是每次查詢都實(shí)例化一次。
3.濫用單例可能導(dǎo)致連接池溢出,這個(gè)問題應(yīng)該只存在于 java 中或類似得,猜測(cè):因?yàn)閖ava采用數(shù)據(jù)庫連接池技術(shù),因?yàn)閖ava是持久化服務(wù),濫用單例導(dǎo)致連接得不到釋放,內(nèi)存不斷上升導(dǎo)致溢出。而php這種請(qǐng)求結(jié)束,所有連接及內(nèi)存都會(huì)釋放,不存在這個(gè)問題。
4.所有的設(shè)計(jì)模式都是為了要實(shí)現(xiàn)功能而服務(wù),所以需要先看你想實(shí)現(xiàn)什么東西。靈活運(yùn)用各種模式,以及其變種,才能寫出更好的代碼。。。
所以不用執(zhí)著于你的四個(gè)問題是否有答案,知道有單例這個(gè)東西,知道多個(gè)示例與單個(gè)示例的區(qū)別,然后你的代碼需要優(yōu)化的時(shí)候,按照自己的需求來就行
首先,我們來看一個(gè)完整的
、規(guī)范的
、簡(jiǎn)單的
單例模式的例子:
<?php
class User {
//靜態(tài)變量保存全局實(shí)例
private static $_instance = null;
//私有構(gòu)造函數(shù),防止外界實(shí)例化對(duì)象
private function __construct() {
}
//私有克隆函數(shù),防止外辦克隆對(duì)象
private function __clone() {
}
//靜態(tài)方法,單例統(tǒng)一訪問入口
static public function getInstance() {
if (is_null ( self::$_instance ) || !isset ( self::$_instance )) {
self::$_instance = new self ();
}
return self::$_instance;
}
public function getName() {
echo 'hello world!';
}
}
$user = User::getInstance();
?>
下面回答問題:
1、你可以隨便改你所謂的單例模式類,但是單例的核心是不能變的:產(chǎn)出一個(gè)實(shí)例;每次使用同一個(gè)實(shí)例對(duì)象;
;如果你把private
改成protected
可以,但是這就無限實(shí)例了不是嗎?不符合單例模式的設(shè)計(jì)規(guī)范呀;
2、這就是php
的變量生命周期問題了。php
所有的變量生命周期,一般情況下只存在于請(qǐng)求開始->請(qǐng)求結(jié)束
,每次請(qǐng)求每個(gè)變量重新被賦值,每個(gè)對(duì)象被重新實(shí)例化;請(qǐng)求結(jié)束,自動(dòng)釋放;單例模式的的意義是:對(duì)象只被實(shí)例化一次,每次調(diào)用返回同一個(gè)實(shí)例;你的單例的生命周期只存在于這一請(qǐng)求過程中,請(qǐng)求結(jié)束,就沒了。再次請(qǐng)求,從新生成新的單例;沒毛病呀
3、濫用什么服務(wù)都會(huì)造成不好的影響;就你現(xiàn)在舉這個(gè)例子而言,對(duì)數(shù)據(jù)庫鏈接使用單例模式的話,每次使用的時(shí)候,都是用的同一靜態(tài)內(nèi)存
區(qū)(類中static聲明的變量默認(rèn)保存在靜態(tài)內(nèi)存區(qū)中)的變量,所以只要實(shí)例化一次,之后在同一請(qǐng)求中使用的時(shí)候,就不會(huì)增加額外的數(shù)據(jù)庫連接對(duì)象了。
而你說的連接池
指的是數(shù)據(jù)庫的連接池吧,這個(gè)連接池是有內(nèi)存限制,也有最大,最小連接限制,而且是可以在mysql的配置文件中設(shè)置的。具體請(qǐng)參考《MySql數(shù)據(jù)庫連接池專題》的介紹。
4、對(duì)TP的源碼沒看過,不方便回答。
以上。
北大青鳥APTECH成立于1999年。依托北京大學(xué)優(yōu)質(zhì)雄厚的教育資源和背景,秉承“教育改變生活”的發(fā)展理念,致力于培養(yǎng)中國(guó)IT技能型緊缺人才,是大數(shù)據(jù)專業(yè)的國(guó)家
北大青鳥中博軟件學(xué)院創(chuàng)立于2003年,作為華東區(qū)著名互聯(lián)網(wǎng)學(xué)院和江蘇省首批服務(wù)外包人才培訓(xùn)基地,中博成功培育了近30000名軟件工程師走向高薪崗位,合作企業(yè)超4
中公教育集團(tuán)創(chuàng)建于1999年,經(jīng)過二十年潛心發(fā)展,已由一家北大畢業(yè)生自主創(chuàng)業(yè)的信息技術(shù)與教育服務(wù)機(jī)構(gòu),發(fā)展為教育服務(wù)業(yè)的綜合性企業(yè)集團(tuán),成為集合面授教學(xué)培訓(xùn)、網(wǎng)
達(dá)內(nèi)教育集團(tuán)成立于2002年,是一家由留學(xué)海歸創(chuàng)辦的高端職業(yè)教育培訓(xùn)機(jī)構(gòu),是中國(guó)一站式人才培養(yǎng)平臺(tái)、一站式人才輸送平臺(tái)。2014年4月3日在美國(guó)成功上市,融資1
曾工作于聯(lián)想擔(dān)任系統(tǒng)開發(fā)工程師,曾在博彥科技股份有限公司擔(dān)任項(xiàng)目經(jīng)理從事移動(dòng)互聯(lián)網(wǎng)管理及研發(fā)工作,曾創(chuàng)辦藍(lán)懿科技有限責(zé)任公司從事總經(jīng)理職務(wù)負(fù)責(zé)iOS教學(xué)及管理工作。
浪潮集團(tuán)項(xiàng)目經(jīng)理。精通Java與.NET 技術(shù), 熟練的跨平臺(tái)面向?qū)ο箝_發(fā)經(jīng)驗(yàn),技術(shù)功底深厚。 授課風(fēng)格 授課風(fēng)格清新自然、條理清晰、主次分明、重點(diǎn)難點(diǎn)突出、引人入勝。
精通HTML5和CSS3;Javascript及主流js庫,具有快速界面開發(fā)的能力,對(duì)瀏覽器兼容性、前端性能優(yōu)化等有深入理解。精通網(wǎng)頁制作和網(wǎng)頁游戲開發(fā)。
具有10 年的Java 企業(yè)應(yīng)用開發(fā)經(jīng)驗(yàn)。曾經(jīng)歷任德國(guó)Software AG 技術(shù)顧問,美國(guó)Dachieve 系統(tǒng)架構(gòu)師,美國(guó)AngelEngineers Inc. 系統(tǒng)架構(gòu)師。