2011-09-10 14 views
6

मैंने देखा है कि सभी सिंगलटन पैटर्न ऑब्जेक्ट के संदर्भ का उपयोग यह निर्धारित करने के लिए करते हैं कि ऑब्जेक्ट को तुरंत चालू किया गया है या नहीं। हालांकि, अगर मैं केवल एक डीबी कनेक्शन की गारंटी देने के लिए सिंगलटन का उपयोग कर रहा हूं, तो ऐसा करने के लिए डीबी कनेक्शन संसाधन लिंक का उपयोग क्यों न करें? यहां वह कोड है जिसका मैं उपयोग कर रहा हूं। (पीएस: यह ठीक काम करता है)। मैं आसानी से अपनी कक्षाओं को खोजने में सक्षम होने के लिए टिप्पणी का उपयोग करता हूं।एक सरल सिंगलटन

/*one*/ 

class one 
    { 
    public static $db; 
    private function __construct() 
    { 
    self::$db=new mysqli(DB_HOST, DB_USER, DB_PASS, DB_DATABASE); 
    } 
    public static function get() 
    { 
    if(self::$db==NULL) 
     { 
     new self(); 
     } 
    return self::$db; 
    } 
    } 
+1

सरलता के लिए +1! – Clive

+1

अभी भी सिंगलटन है। वहां कुछ असामान्य नहीं है, मैं कहूंगा। – Smar

+2

एरर ... कोई भी नहीं देखता कि प्राप्त विधि एक अलग वस्तु देता है? – Macmade

उत्तर

5

पीएचपी में, एक निर्माता वापस नहीं करता है।

तो आपकी get विधि one ऑब्जेक्ट देता है, पहली बार इसे कॉल किया जाता है, फिर mysqli ऑब्जेक्ट। शायद आप जो चाहते हैं वह नहीं।

if(self::$_db == NULL) 
{ 
    return new self(); // Here you return an object of class one 
} 
else 
{ 
    return self::$_db; // Here you return an object of type mysqli 
} 

आप mysqli वस्तु वापस करना चाहते हैं, तो आप एक सिंगलटन की जरूरत नहीं है के रूप में एक वस्तु किसी अन्य वस्तु का एक उदाहरण वापस जाने के लिए नहीं है कि केवल यहाँ का एक उदाहरण बनाने के लिए कोई जरूरत नहीं है।

इस तरह के मामले में रजिस्ट्री पैटर्न बेहतर होगा।

यदि आपको विधियां (आपके डीबी ऑब्जेक्ट के लिए एक रैपर) प्रदान करने की आवश्यकता है, तो एक असली सिंगलटन बनाएं।

संपादित

मैं अपने अपडेट किए गए कोड की जाँच की। अब आप हमेशा mysqli उदाहरण वापस लौटते हैं। लेकिन आपको अपनी वस्तु को तुरंत चालू करने की आवश्यकता नहीं है। यही कारण है कि, के रूप में सुनहरा कहा पूरी तरह से बेकार है ...

तुम सच में पैटर्न के अपनी तरह के साथ जाना चाहते हैं, तो, अपने स्थिर उदाहरण में जांच करता है कि self::dbNULL है। यदि हां, mysqli उदाहरण बनाता है, और इसे self::db पर असाइन करें। फिर इसे वापस कर देता है।

public static getDatabaseInstance() 
{ 
    if(self::$_db == NULL) 
    { 
     self::$_db = new mysqli(...); 
    } 

    return self::$_db; 
} 

भी निर्माता को निजी सेट करें, इसलिए उपयोगकर्ता आपकी कक्षा के बेकार उदाहरण नहीं बना पाएंगे। या बेहतर इसे सार्वजनिक करने और एक अपवाद फेंक:

public function __construct() 
{ 
    throw new Exception('This class is not supposed to be instantiated'); 
} 
+0

PHP दस्तावेज़ से: 'शून्य __construct ([मिश्रित $ args [, $ ...]])'। 'शून्य 'देखें? http://php.net/manual/en/language.oop5.decon.php – Macmade

+1

इसका मतलब है कि वापसी मूल्य को अनदेखा किया जाता है। तो अगर आप कुछ (दूसरी वस्तु) वापस करते हैं, तो यह 'new' द्वारा तत्काल ऑब्जेक्ट के प्रकार को संशोधित नहीं करेगा। – Macmade

+0

मेरा संपादन देखें ...:) – Macmade

0
class one 
{ 
    private static $_selfInstance; 
    public $db; 
    private function __construct() 
    { 
    } 
    public function getDb() 
    { 
     if($this->db == null) 
     $this->db=new mysqli(DB_HOST, DB_USER, DB_PASS, DB_DATABASE); 
     return $this->db; 

    } 

    public static function getInstance() 
    { 
     if(!(self::$_selfInstance instanceof self)) { 
     self::$_selfInstance= new self(); 
     } 
     return self::$_selfInstance; 
    } 
} 

पहुँच

$db = one::getInstance()->getDb(); 
+1

क्या '_ _selfInstace' में दूसरा' n' छोड़ने का कोई कारण था? – jcolebrand

1

मान लिया जाये कि मैं सही ढंग से अपने प्रश्न को पार्स कर रहा हूँ, आप पूछ रहे हैं अगर यह लगता है कि आप केवल एक दृष्टांत बनाने के लिए $db की तुच्छता का उपयोग करना उचित नहीं है; यह चीजों को करने का एक बिल्कुल वैध तरीका है, और वास्तव में मैं सिफारिश करता हूं। PHP null स्पष्ट रूप से "कोई मान" वाले चर का प्रतिनिधित्व करने का इरादा है - सिंगलटन पैटर्न की अनियमित स्थिति के लिए एकदम सही फिट।

आमतौर पर, इन चीजों को सिर्फ एक सहज नाम से बुलाया जाएगा, उदा। SomeAppDbConn

0

जैसा कि मैकमेड पहले से ही इंगित करता है, constructor विधि कुछ भी नहीं बल्कि कक्षा का एक उदाहरण देता है। मान लीजिए कि आप हमेशा mysqli का एक ही उदाहरण चाहते हैं, यहां मैं यह कैसे करूँगा।

class DBInstance 
{ 
    protected static $db; 

    private function __construct() 
    { 
     // intentionally empty 
    } 

    public static function get() 
    { 
     if(self::$db === NULL) 
     { 
      self::$db=new mysqli(DB_HOST, DB_USER, DB_PASS, DB_DATABASE); 
     } 

     return self::$db; 
    } 
} 

यह सबसे निश्चित रूप से instantiated वर्ग से इन्स्टेन्शियशन को अलग करने का एक अतिरिक्त बोनस के साथ एक सिंगलटन पैटर्न है।

+0

एक रजिस्ट्री बेहतर होगी, IMHO। या कम से कम, कक्षा के बेकार तत्काल से बचने के लिए, कन्स्ट्रक्टर निजी घोषित करता है। – Macmade

+0

ठीक है आप हैं और मैं रजिस्ट्री का उपयोग करने पर आपसे सहमत हूं। दूसरी तरफ, इस विधि का उपयोग करना निश्चित रूप से तेज़ है यदि आप वास्तव में एक छोटा ऐप विकसित कर रहे हैं जहां डेटाबेस कनेक्शन केवल इस पैटर्न में फिट है। तुम क्या सोचते हो? – gilden

+0

निश्चित रूप से, और ऐसा लगता है कि वह इसे इस तरह से चाहता है ...:) – Macmade

3

परिभाषित यह काम करता है ठीक :)

करने का प्रयास करें:

  • तरीकों में से दोनों से लौटे वस्तु हैश तुलना (बात है जब आप वस्तु क्लोनिंग का उपयोग करता है)
  • का उपयोग कर डीबी से कनेक्ट विभिन्न प्रमाण-पत्र (उदाहरण के लिए यूनिट परीक्षणों में)
  • डीबी से डिस्कनेक्ट करें और फिर से कनेक्ट करें
  • के उदाहरण को रीसेट करें ऑब्जेक्ट (अब new का उपयोग कर 1000 ऑब्जेक्ट्स को मेमोरी भरता है)
  • इस कक्षा के उदाहरण में कुछ अन्य डेवलपर को बताने के लिए बताएं, वह निश्चित रूप से one::getInstance() विधि देखेंगे। वह इस वर्ग के व्यवहार का अनुमान कैसे लगा सकता है?

सिंगलेट वैश्विक स्थिति के बारे में हैं। ऐसा लगता है कि आपके पास वैश्विक स्थिति + कुछ गड़बड़ है।