नीचे दिया गया उत्तर गलत है, लेकिन मैं इसे दूसरों से सीखने के लिए रखूंगा (नीचे देखें)
में ExampleA
, आप एक से Config
अधिक वर्गों में एक ही उदाहरण का उपयोग कर सकते हैं । हालांकि, अगर Config
पूरे आवेदन के भीतर केवल एक ही उदाहरण होना चाहिए, तो Config
कई उदाहरण होने से बचने के लिए सिंगलटन पैटर्न को लागू करने पर विचार करें Config
। और अगर Config
एक सिंगलटन है, तो आप इसके बजाय निम्नलिखित कर सकते हैं:
class ExampleA
{
private $config;
public function __construct()
{
$this->config = Config->getInstance();
}
}
$exampleA = new ExampleA();
में ExampleB
, दूसरे हाथ पर, आप हमेशा का एक अलग इंस्टेंस मिल जाएगा Config
के प्रत्येक उदाहरण के लिए ExampleB
।
आपको किस संस्करण को वास्तव में लागू करना चाहिए यह इस बात पर निर्भर करता है कि आवेदन किस तरह से उदाहरणों को संभालेगा Config
:
- यदि प्रत्येक उदाहरण का
ExampleX
अलग उदाहरण होना चाहिए, तो Config
साथ जाएं ExampleB
;
- यदि प्रत्येक का उदाहरण
ExampleX
(और केवल एक) का साझा होगा Config
, का उपयोग करें ExampleA with Config Singleton
;
- अगर उदाहरण के
ExampleX
विभिन्न उदाहरणों का उपयोग कर सकते हैं Config
, के साथ छड़ी ExampleA
।
क्यों Config
एक सिंगलटन में परिवर्तित करना गलत है:
मुझे यह स्वीकार करना चाहिए कि मैंने कल ही सिंगलटन पैटर्न के बारे में सीखा था ( डिजाइन पैटर्न के हेड फर्स्ट बुक को पढ़ना )। Naively मैं इसके बारे में गया और इसे इस उदाहरण के लिए लागू किया, लेकिन जैसा कि कई ने बताया है, एक तरीका एक और है (कुछ अधिक गूढ़ है और केवल कहा गया है "आप इसे गलत कर रहे हैं!"), यह एक अच्छा विचार नहीं है। इसलिए, दूसरों को वही गलती करने से रोकने के लिए, जो मैंने अभी किया था, यहां इस बात का सारांश दिया गया है कि क्यों सिंगलटन पैटर्न हानिकारक हो सकता है (टिप्पणियों के आधार पर और मुझे जो पता चला है वह इसे दोहरा रहा है):
यदि उदाहरण ExampleA
के Config
लिए अपना स्वयं का संदर्भ प्राप्त होता है , तो कक्षाएं कसकर युग्मित हो जाएंगी। (जैसे कुछ उपवर्ग) के ExampleA
एक अलग संस्करण का उपयोग करने के लिए एक उदाहरण होने का कोई तरीका नहीं होगा Config
। यह भयानक है अगर आप ExampleA
मॉक-अप उदाहरण का उपयोग करके परीक्षण करना चाहते हैं Config
क्योंकि इसे प्रदान करने का कोई तरीका नहीं है ExampleA
।
वहाँ का आधार एक होगा, और केवल एक, Config
शायद का उदाहरण अब धारण करता है , लेकिन आप हमेशा यह सुनिश्चित नहीं कर सकते हैं कि भविष्य में भी यही होगा । यदि बाद में कुछ बिंदु पर यह पता चलता है कि Config
इच्छा के कई उदाहरण वांछनीय होंगे, तो कोड को फिर से लिखे बिना इसे प्राप्त करने का कोई तरीका नहीं है।
भले ही एक-और-केवल एक उदाहरण Config
सभी अनंत काल के लिए सही है, लेकिन ऐसा हो सकता है कि आप कुछ उपवर्गों का उपयोग करने में सक्षम होना चाहते हैं Config
(जबकि अभी भी केवल एक उदाहरण है)। लेकिन, चूंकि कोड सीधे उदाहरण के माध्यम से getInstance()
प्राप्त करता है Config
, जो कि एक static
विधि है, इसलिए उपवर्ग प्राप्त करने का कोई तरीका नहीं है। फिर से, कोड को फिर से लिखा जाना चाहिए।
ExampleA
उपयोग किए जाने वाले तथ्य को Config
छिपाया जाएगा, कम से कम जब केवल एपीआई को देखा जाएगा ExampleA
। यह बुरी बात हो सकती है या नहीं भी हो सकती है, लेकिन व्यक्तिगत रूप से मुझे लगता है कि यह एक नुकसान जैसा लगता है; उदाहरण के लिए, बनाए रखने के दौरान, यह पता लगाने का कोई सरल तरीका नहीं है Config
कि हर दूसरे वर्ग के कार्यान्वयन को देखे बिना परिवर्तनों से कौन सी कक्षाएं प्रभावित होंगी ।
यहां तक कि अगर तथ्य यह है कि ExampleA
एक सिंगलटन Config
का उपयोग करता है अपने आप में एक समस्या नहीं है, यह अभी भी एक परीक्षण के दृष्टिकोण से एक समस्या बन सकता है। सिंगलटन ऑब्जेक्ट राज्य को ले जाएगा जो कि आवेदन की समाप्ति तक जारी रहेगा। इकाई परीक्षण चलाते समय यह एक समस्या हो सकती है क्योंकि आप चाहते हैं कि एक परीक्षण को दूसरे से अलग किया जाए (यानी कि एक परीक्षण निष्पादित होने पर दूसरे के परिणाम को प्रभावित नहीं करना चाहिए)। इसे ठीक करने के लिए, प्रत्येक परीक्षण रन (संभावित रूप से पूरे एप्लिकेशन को पुनरारंभ करने) के बीच सिंगलटन ऑब्जेक्ट को नष्ट कर दिया जाना चाहिए, जो समय लेने वाली (थकाऊ और कष्टप्रद का उल्लेख नहीं करने के लिए) हो सकता है।
यह कहने के बाद, मुझे खुशी है कि मैंने यह गलती यहाँ की है न कि एक वास्तविक आवेदन के कार्यान्वयन में। वास्तव में, मैं वास्तव में कुछ वर्गों के लिए सिंगलटन पैटर्न का उपयोग करने के लिए अपने नवीनतम कोड को फिर से लिखने पर विचार कर रहा था । हालाँकि मैं बदलावों को आसानी से बदल सकता था (सब कुछ एक एसवीएन में संग्रहीत है, निश्चित रूप से), फिर भी मैंने इसे करने में समय बर्बाद किया होगा।