C++ के लिए Dependency Injection कंटेनर: विस्तृत समीक्षा और व्यावहारिक उदाहरण
आधुनिक C++ डेवलपमेंट में Inversion of Control (IoC) और Dependency Injection (DI) के सिद्धांतों का उपयोग तेजी से बढ़ रहा है। ये पैटर्न कमजोर रूप से जुड़ा, परीक्षण योग्य और आसानी से विस्तार योग्य कोड बनाने में मदद करते हैं। Java या C# जैसी मैनेज्ड मेमोरी वाली भाषाओं के विपरीत, C++ में बिल्ट-इन रिफ्लेक्शन नहीं है, इसलिए DI कंटेनरों को लागू करने के लिए टेम्पलेट मेटाप्रोग्रामिंग और आधुनिक मानकों (C++11/14/17/20) की आवश्यकता होती है।
इस लेख में हम C++ में डिपेंडेंसी इंजेक्शन के तीन लोकप्रिय तरीकों पर चर्चा करेंगे: Boost.DI, Google Fruit और Kangaru लाइब्रेरीज़, साथ ही मैकेनिज्म को समझने के लिए एक सरल कंटेनर खुद बनाएंगे।
Dependency Injection क्या है?
Dependency Injection एक तकनीक है जिसमें ऑब्जेक्ट अपनी डिपेंडेंसी बाहर से प्राप्त करता है, न कि खुद बनाता है। DI के मुख्य प्रकार हैं:
- Constructor Injection — डिपेंडेंसी कंस्ट्रक्टर के माध्यम से पास की जाती है।
- Setter Injection — डिपेंडेंसी सेटर मेथड के माध्यम से सेट की जाती है।
- Interface Injection — डिपेंडेंसी इंटरफ़ेस के माध्यम से पास की जाती है।
DI के बिना उदाहरण (मजबूत कपलिंग):
class Logger {
public:
void log(const std::string& msg) { /* फ़ाइल में लिखना */ }
};
class Service {
Logger logger; // मजबूत डिपेंडेंसी
public:
void doWork() { logger.log("काम पूरा हुआ"); }
};
DI के साथ उदाहरण (कमजोर कपलिंग):
class ILogger {
public:
virtual ~ILogger() = default;
virtual void log(const std::string& msg) = 0;
};
class ConsoleLogger : public ILogger {
public:
void log(const std::string& msg) override { std::cout << msg << std::endl; }
};
class Service {
std::shared_ptr<ILogger> logger;
public:
explicit Service(std::shared_ptr<ILogger> l) : logger(std::move(l)) {}
void doWork() { logger->log("काम पूरा हुआ"); }
};
C++ के लिए DI कंटेनरों की समीक्षा
1. Boost.DI
Boost.DI सबसे लोकप्रिय लाइब्रेरीज़ में से एक है। यह डिपेंडेंसी को स्वचालित रूप से हल करने के लिए C++14/17 टेम्पलेट का उपयोग करती है। यह पॉलीमॉर्फिज़्म, स्कोप (singleton, unique) और मॉड्यूलर कॉन्फ़िगरेशन को सपोर्ट करती है।
उपयोग का उदाहरण:
#include <boost/di.hpp>
#include <iostream>
namespace di = boost::di;
class IWriter {
public:
virtual ~IWriter() = default;
virtual void write(const std::string&) = 0;
};
class ConsoleWriter : public IWriter {
public:
void write(const std::string& msg) override {
std::cout << msg << std::endl;
}
};
class App {
std::shared_ptr<IWriter> writer;
public:
explicit App(std::shared_ptr<IWriter> w) : writer(std::move(w)) {}
void run() { writer->write("Boost.DI से नमस्ते!"); }
};
int main() {
auto injector = di::make_injector(
di::bind<IWriter>.to<ConsoleWriter>()
);
auto app = injector.create<std::unique_ptr<App>>();
app->run();
return 0;
}
फायदे: मजबूत टाइपिंग, न्यूनतम runtime ओवरहेड, C++14/17 सपोर्ट।
नुकसान: जटिल कंपाइलेशन एरर मैसेज, बिल्ड टाइम बढ़ना।
2. Google Fruit
Google Fruit Google द्वारा बनाया गया एक कंटेनर है जो C++11 पर काम करता है। यह कंपोनेंट रजिस्टर करने के लिए मैक्रोज़ का उपयोग करता है और कंस्ट्रक्टर के माध्यम से इंजेक्शन को सपोर्ट करता है।
उदाहरण:
#include <fruit/fruit.h>
#include <iostream>
class IWriter {
public:
virtual void write(const std::string&) = 0;
};
class ConsoleWriter : public IWriter {
public:
INJECT(ConsoleWriter()) = default;
void write(const std::string& msg) override {