C++ में डिपेंडेंसी इंजेक्शन का परिचय
\n\nजब आप C++ सीखना शुरू करते हैं, तो आप सरल प्रोग्राम लिखते हैं जहाँ क्लास अपनी डिपेंडेंसी सीधे बनाते हैं। उदाहरण के लिए, क्लास Car खुद Engine ऑब्जेक्ट बनाता है। यह छोटे प्रोजेक्ट के लिए काम करता है, लेकिन जब कोड बढ़ता है, तो यह दृष्टिकोण गंभीर समस्याएँ पैदा करता है: कोड कसकर जुड़ा हो जाता है, इसका परीक्षण और बदलाव करना मुश्किल हो जाता है।
डिपेंडेंसी इंजेक्शन (DI) एक डिज़ाइन पैटर्न है जिसमें ऑब्जेक्ट अपनी डिपेंडेंसी बाहर से प्राप्त करता है, न कि उन्हें स्वयं बनाता है। यह SOLID के प्रमुख सिद्धांतों में से एक है, विशेष रूप से डिपेंडेंसी इनवर्ज़न सिद्धांत (Dependency Inversion Principle)।
\n\nइस लेख में, हम समझेंगे कि C++ में डिपेंडेंसी इंजेक्शन क्या है, इसकी आवश्यकता क्यों है, और इसे व्यवहार में कैसे लागू किया जाए। आप देखेंगे कि यह पैटर्न कोड को लचीला, परीक्षण योग्य और रखरखाव योग्य कैसे बनाता है।
\n\nDI के बिना समस्या: कसकर जुड़ाव की समस्या
\n\nकल्पना करें कि आप एक स्मार्ट होम प्रबंधन प्रणाली लिख रहे हैं। एक क्लास SmartLight है जो बल्ब को नियंत्रित करता है। एक सरल कार्यान्वयन में, यह स्वयं Bulb ऑब्जेक्ट बनाता है:
#include <iostream>\n#include <string>\n\nclass Bulb {\npublic:\n void turnOn() { std::cout << "बल्ब चालू\\n"; }\n void turnOff() { std::cout << "बल्ब बंद\\n"; }\n};\n\nclass SmartLight {\nprivate:\n Bulb bulb; // कसकर जुड़ाव\npublic:\n void activate() { bulb.turnOn(); }\n void deactivate() { bulb.turnOff(); }\n};\n\nint main() {\n SmartLight light;\n light.activate();\n return 0;\n}\n\nयहाँ क्या समस्याएँ हैं?
\n\n- \n
- कसकर जुड़ाव:
SmartLightBulbसे अटूट रूप से जुड़ा हुआ है। यदि आप कोई दूसरा बल्ब (जैसे स्मार्ट LED या Phillips Hue) उपयोग करना चाहते हैं, तो आपको क्लास का कोड बदलना होगा। \n - परीक्षण में कठिनाई: आप यूनिट टेस्ट में वास्तविक बल्ब को "नकली" (mock) से नहीं बदल सकते। \n
- SRP का उल्लंघन: क्लास
SmartLightदो काम करता है: बल्ब को नियंत्रित करना और उसे बनाना। \n
यह कसकर जुड़ाव (tight coupling) का एक उत्कृष्ट उदाहरण है, जिसे डिपेंडेंसी इंजेक्शन समाप्त करने का प्रयास करता है।
\n\nC++ में डिपेंडेंसी इंजेक्शन क्या है: मुख्य अवधारणाएँ
\n\nडिपेंडेंसी इंजेक्शन (DI) एक तकनीक है जिसमें ऑब्जेक्ट अपनी डिपेंडेंसी (आमतौर पर कंस्ट्रक्टर, सेटर या इंटरफ़ेस के माध्यम से) बाहरी स्रोत से प्राप्त करता है, न कि उन्हें स्वयं बनाता है। मुख्य विचार: "यह मत पूछो कि तुम्हें क्या चाहिए - तुम्हें यह दिया जाएगा"।
\n\nC++ में, DI को इसके माध्यम से कार्यान्वित किया जाता है:
\n\n- \n
- इंटरफ़ेस (एब्सट्रैक्ट क्लास): डिपेंडेंसी को ठोस क्लास के बजाय एब्सट्रैक्ट प्रकारों के माध्यम से घोषित किया जाता है। \n
- पैरामीटर के साथ कंस्ट्रक्टर: डिपेंडेंसी कंस्ट्रक्टर के माध्यम से पास की जाती है (सबसे सामान्य तरीका)। \n
- सेटर: ऑब्जेक्ट बनने के बाद डिपेंडेंसी सेट की जाती है। \n
- डिपेंडेंसी कंटेनर: विशेष लाइब्रेरी जो स्वचालित रूप से डिपेंडेंसी बनाती और इंजेक्ट करती हैं (जैसे,
boost.di)। \n
आइए DI का उपयोग करके स्मार्ट लाइट के उदाहरण को फिर से लिखें:
\n\n#include <iostream>\n#include <memory>\n\n// बल्ब के लिए एब्सट्रैक्ट इंटरफ़ेस\nclass IBulb {\npublic:\n virtual void turnOn() = 0;\n virtual void turnOff() = 0;\n virtual ~IBulb() = default;\n};\n\n// ठोस कार्यान्वयन: सामान्य बल्ब\nclass Bulb : public IBulb {\npublic:\n void turnOn() override { std::cout << "बल्ब चालू\\n"; }\n void turnOff() override { std::cout << "बल्ब बंद\\n"; }\n};\n\n// दूसरा कार्यान्वयन: LED बल्ब\nclass LedBulb : public IBulb {\npublic:\n void turnOn() override { std::cout << "LED बल्ब चालू\\n"; }\n void turnOff() override {