कहो कि मेरे पास एक वर्ग है Foobar
जो उपयोग करता है (निर्भर करता है) वर्ग Widget
। अच्छे राजभाषा दिनों में, Widget
वूलुद को एक क्षेत्र के रूप में Foobar
, या शायद एक स्मार्ट सूचक के रूप में घोषित किया जा सकता है यदि बहुरूपी व्यवहार की आवश्यकता होती है, और इसे निर्माणकर्ता में आरंभ किया जाएगा:
class Foobar {
Widget widget;
public:
Foobar() : widget(blah blah blah) {}
// or
std::unique_ptr<Widget> widget;
public:
Foobar() : widget(std::make_unique<Widget>(blah blah blah)) {}
(…)
};
और हम सब सेट और किया जाएगा। दुर्भाग्य से, आज, जावा बच्चे इसे देखकर एक बार हम पर हँसेंगे, और सही रूप में, जैसा कि यह युगल Foobar
और Widget
एक साथ है। समाधान सरल प्रतीत होता है: निर्भरता के निर्माण को Foobar
कक्षा से बाहर करने के लिए निर्भरता इंजेक्शन लागू करें । लेकिन फिर, C ++ हमें निर्भरता के स्वामित्व के बारे में सोचने के लिए मजबूर करता है। तीन समाधान दिमाग में आते हैं:
अद्वितीय सूचक
class Foobar {
std::unique_ptr<Widget> widget;
public:
Foobar(std::unique_ptr<Widget> &&w) : widget(w) {}
(…)
}
Foobar
Widget
उस पर एकमात्र स्वामित्व का दावा किया जाता है। इसके निम्नलिखित फायदे हैं:
- प्रदर्शन पर प्रभाव नगण्य है।
- यह सुरक्षित है, क्योंकि यह
Foobar
जीवनकाल को नियंत्रित करता हैWidget
, इसलिए यह सुनिश्चित करता है किWidget
अचानक गायब न हो। - यह सुरक्षित है कि
Widget
रिसाव नहीं होगा और जब जरूरत नहीं होगी तो ठीक से नष्ट हो जाएगा।
हालाँकि, यह लागत पर आता है:
- यह इस बात पर प्रतिबंध लगाता है कि किस तरह से
Widget
उदाहरणों का उपयोग किया जा सकता है, जैसे कोई स्टैक-आबंटित नहीं कियाWidgets
जा सकता है, कोईWidget
साझा नहीं किया जा सकता है।
साझा किया गया सूचक
class Foobar {
std::shared_ptr<Widget> widget;
public:
Foobar(const std::shared_ptr<Widget> &w) : widget(w) {}
(…)
}
यह संभवतः निकटतम समकक्ष ओ.टी. जावा और अन्य कचरा एकत्र की गई भाषाएँ हैं। लाभ:
- अधिक सार्वभौमिक, क्योंकि यह निर्भरता को साझा करने की अनुमति देता है।
unique_ptr
समाधान की सुरक्षा (अंक 2 और 3) बनाए रखता है ।
नुकसान:
- कोई साझाकरण शामिल नहीं होने पर संसाधनों को बर्बाद करता है।
- अभी भी ढेर आवंटन की आवश्यकता है और स्टैक-आवंटित वस्तुओं को रोकना है।
सादा ओएल 'का सूचक
class Foobar {
Widget *widget;
public:
Foobar(Widget *w) : widget(w) {}
(…)
}
कच्चे पॉइंटर को कक्षा के अंदर रखें और स्वामित्व का बोझ किसी और पर स्थानांतरित करें। पेशेवरों:
- यह जितना आसान हो सकता है।
- यूनिवर्सल, बस किसी भी स्वीकार करता है
Widget
।
विपक्ष:
- अब सुरक्षित नहीं है।
- एक और इकाई का परिचय देता है जो दोनों के स्वामित्व के लिए जिम्मेदार है
Foobar
औरWidget
।
कुछ पागल टेम्पलेट मेटाप्रोग्रामिंग
केवल एक ही लाभ जो मैं सोच सकता हूं कि मैं उन सभी पुस्तकों को पढ़ पाऊंगा, जिनके लिए मुझे समय नहीं मिला, जबकि मेरा सॉफ्टवेयर बन रहा है;)
मैं तीसरे समाधान की ओर झुकता हूं, क्योंकि यह सबसे सार्वभौमिक है, कुछ Foobars
भी वैसे भी प्रबंधित करना है, इसलिए प्रबंधन Widgets
सरल परिवर्तन है। हालांकि, कच्चे पॉइंटर्स का उपयोग मुझे परेशान करता है, दूसरी ओर स्मार्ट पॉइंटर समाधान मुझे गलत लगता है, क्योंकि वे निर्भरता के उपभोक्ता को प्रतिबंधित करते हैं कि निर्भरता कैसे बनाई जाती है।
क्या मैं कुछ भूल रहा हूँ? या सिर्फ C ++ में निर्भरता इंजेक्शन तुच्छ नहीं है? क्या अपनी निर्भरता को स्वयं वर्गीकृत करना चाहिए या केवल उनका निरीक्षण करना चाहिए?
Foobar
एकमात्र मालिक है? पुराने मामले में यह सरल है। लेकिन डीआई के साथ समस्या, जैसा कि मैं इसे देखता हूं, जैसे कि यह अपनी निर्भरता के निर्माण से वर्ग को डिकॉय करता है, यह उन निर्भरता के स्वामित्व से भी डिकॉय करता है (जैसा कि स्वामित्व निर्माण से बंधा है)। जावा जैसे कचरा एकत्रित वातावरण में, यह कोई समस्या नहीं है। C ++ में, यह है।
std::unique_ptr
जाने का रास्ता है। आपstd::move()
संसाधन के स्वामित्व को ऊपरी दायरे से कक्षा में स्थानांतरित करने के लिए उपयोग कर सकते हैं ।