एकल गीत । के बारे में 10-15 साल पहले, एकमात्र थे बड़ा डिजाइन पैटर्न के बारे में पता करने के लिए। हालाँकि, आजकल उन्हें नीचा दिखाया जाता है। वे बहु-धागा करने के लिए बहुत आसान हैं, लेकिन आपको एक समय में उनके उपयोग को एक धागे तक सीमित करना चाहिए, जो हमेशा वह नहीं है जो आप चाहते हैं। वैश्विक चरों के साथ जीवन रेखाओं को ट्रैक करना उतना ही मुश्किल है।
एक विशिष्ट एकल वर्ग कुछ इस तरह दिखाई देगा:
class MyClass
{
private:
static MyClass* _instance;
MyClass() {} //private constructor
public:
static MyClass* getInstance();
void method();
};
...
MyClass* MyClass::_instance = NULL;
MyClass* MyClass::getInstance()
{
if(_instance == NULL)
_instance = new MyClass(); //Not thread-safe version
return _instance;
//Note that _instance is *never* deleted -
//it exists for the entire lifetime of the program!
}
निर्भरता इंजेक्शन (DI) । यह सिर्फ एक निर्माता पैरामीटर के रूप में सेवा पास करने का मतलब है। एक सेवा को कक्षा में पास करने के लिए पहले से ही मौजूद होना चाहिए, इसलिए दो सेवाओं के लिए एक दूसरे पर भरोसा करने का कोई तरीका नहीं है; 98% मामलों में, यह वही है जो आप चाहते हैं (और अन्य 2% के लिए, आप हमेशा एक setWhatever()
विधि बना सकते हैं और सेवा में पास हो सकते हैं ) । इस वजह से, DI के पास अन्य विकल्पों की तरह ही युग्मन समस्याएं नहीं हैं। इसका उपयोग मल्टीथ्रेडिंग के साथ किया जा सकता है, क्योंकि प्रत्येक थ्रेड में बस हर सेवा का अपना उदाहरण हो सकता है (और केवल उन लोगों को साझा करता है जो इसे पूरी तरह से आवश्यक हैं)। यदि आप इस बारे में परवाह करते हैं तो यह कोड यूनिट-टेस्ट करने योग्य भी बनाता है।
निर्भरता इंजेक्शन के साथ समस्या यह है कि यह अधिक मेमोरी लेता है; अब हर वर्ग के प्रत्येक उदाहरण के लिए हर उस सेवा के संदर्भों की आवश्यकता होगी जिसका वह उपयोग करेगा। इसके अलावा, जब आपको बहुत अधिक सेवाएँ होती हैं, तो इसका उपयोग करने पर गुस्सा आता है; ऐसी रूपरेखाएँ हैं जो अन्य भाषाओं में इस समस्या को कम करती हैं, लेकिन C ++ के परावर्तन में कमी के कारण, C ++ में DI चौखटे केवल मैन्युअल रूप से करने की तुलना में और भी अधिक काम करते हैं।
//Example of dependency injection
class Tower
{
private:
MissileCreationService* _missileCreator;
CreepLocatorService* _creepLocator;
public:
Tower(MissileCreationService*, CreepLocatorService*);
}
//In order to create a tower, the creating-class must also have instances of
// MissileCreationService and CreepLocatorService; thus, if we want to
// add a new service to the Tower constructor, we must add it to the
// constructor of every class which creates a Tower as well!
//This is not a problem in languages like C# and Java, where you can use
// a framework to create an instance and inject automatically.
देखें यह पेज एक और उदाहरण के लिए (Ninject, एक सी # डि ढांचे के लिए प्रलेखन से)।
निर्भरता इंजेक्शन इस समस्या का सामान्य समाधान है, और इसका उत्तर है कि आप StackOverflow.com पर इस तरह के प्रश्नों के लिए सबसे अधिक उत्थान पाएंगे। DI एक प्रकार का व्युत्क्रम नियंत्रण (IoC) है।
सेवा लोकेटर । मूल रूप से, सिर्फ एक वर्ग जो हर सेवा का एक उदाहरण रखता है। आप इसे प्रतिबिंब का उपयोग करके कर सकते हैं , या आप हर बार एक नया उदाहरण जोड़ सकते हैं जब आप एक नई सेवा बनाना चाहते हैं। आपके पास पहले जैसी ही समस्या है - इस लोकेटर तक कक्षाएं कैसे पहुंचती हैं? - जो उपरोक्त किसी भी तरीके से हल किया जा सकता है, लेकिन अब आपको केवल ServiceLocator
दर्जनों सेवाओं के बजाय इसे अपनी कक्षा के लिए करना होगा । यह विधि इकाई-परीक्षण योग्य भी है, यदि आप उस प्रकार की परवाह करते हैं।
सेवा लोकेटर उलटा नियंत्रण (IoC) का एक और रूप है। आमतौर पर, स्वचालित निर्भरता इंजेक्शन करने वाले ढांचे में एक सेवा लोकेटर भी होगा।
XNA (Microsoft का C # गेम प्रोग्रामिंग फ्रेमवर्क) में एक सेवा लोकेटर शामिल है; इसके बारे में अधिक जानने के लिए, इस उत्तर को देखें ।