Rust में डिपेंडेंसी इंजेक्शन का परिचय
डिपेंडेंसी इंजेक्शन (DI) एक डिज़ाइन पैटर्न है जिसमें कोई ऑब्जेक्ट अपनी डिपेंडेंसी को स्वयं बनाने के बजाय बाहर से प्राप्त करता है। Rust में, जहाँ सुरक्षा और प्रदर्शन सर्वोपरि हैं, DI लचीला, परीक्षण योग्य और ढीला-युग्मित कोड बनाने में मदद करता है। इस लेख में, हम ट्रेट्स, जेनेरिक्स और कंटेनरों का उपयोग करके Rust में डिपेंडेंसी इंजेक्शन को लागू करने का तरीका समझेंगे।
रिफ्लेक्शन वाली भाषाओं (Java, C#) के विपरीत, Rust बिल्ट-इन DI फ्रेमवर्क प्रदान नहीं करता है। हालाँकि, इसकी टाइप सिस्टम और स्वामित्व प्रणाली प्रदर्शन को खोए बिना सुरुचिपूर्ण समाधान बनाने की अनुमति देती है।
डिपेंडेंसी इंजेक्शन के मुख्य दृष्टिकोण
Rust में DI को लागू करने के कई तरीके हैं। आइए तीन मुख्य दृष्टिकोणों पर विचार करें।
1. कंस्ट्रक्टर के माध्यम से इंजेक्शन (Constructor Injection)
सबसे सरल और सामान्य तरीका है कंस्ट्रक्टर में डिपेंडेंसी पास करना। यह सुनिश्चित करता है कि ऑब्जेक्ट हमेशा वैध स्थिति में रहे।
// नोटिफिकेशन भेजने के लिए ट्रेट परिभाषित करेंtrait Notifier { fn send(&self, message: &str);}
// Email के लिए कार्यान्वयनstruct EmailNotifier { smtp_server: String,}
impl Notifier for EmailNotifier { fn send(&self, message: &str) { println!("{} के माध्यम से ईमेल भेज रहा है: {}", self.smtp_server, message); }}
// SMS के लिए कार्यान्वयनstruct SmsNotifier { api_key: String,}
impl Notifier for SmsNotifier { fn send(&self, message: &str) { println!("कुंजी {} के साथ SMS भेज रहा है: {}", self.api_key, message); }}
// सेवा जो Notifier का उपयोग करती हैstruct NotificationService { notifier: Box<dyn Notifier>,}
impl NotificationService { // कंस्ट्रक्टर के माध्यम से डिपेंडेंसी इंजेक्शन fn new(notifier: Box<dyn Notifier>) -> Self { NotificationService { notifier } }
fn notify(&self, message: &str) { self.notifier.send(message); }}
fn main() { let email_notifier = Box::new(EmailNotifier { smtp_server: "smtp.example.com".to_string(), }); let service = NotificationService::new(email_notifier); service.notify("Hello, Rust!");}2. जेनेरिक्स के माध्यम से इंजेक्शन (Generic Injection)
जेनेरिक्स का उपयोग करके डायनामिक डिस्पैच से बचा जा सकता है और मोनोमोर्फाइजेशन के माध्यम से प्रदर्शन बढ़ाया जा सकता है।
// वही Notifier ट्रेट, लेकिन सेवा अब सामान्यीकृत हैstruct NotificationService<T: Notifier> { notifier: T,}
impl<T: Notifier> NotificationService<T> { fn new(notifier: T) -> Self { NotificationService { notifier } }
fn notify(&self, message: &str) { self.notifier.send(message); }}
fn main() { let email_notifier = EmailNotifier { smtp_server: "smtp.example.com".to_string(), }; let service = NotificationService::new(email_notifier); service.notify("Hello from generic Rust!");}3. डिपेंडेंसी कंटेनर के माध्यम से इंजेक्शन
जटिल प्रोजेक्ट्स के लिए, डिपेंडेंसी कंटेनर का उपयोग करना सुविधाजनक होता है जो ऑब्जेक्ट्स के निर्माण और जीवनकाल का प्रबंधन करता है। Rust में, मैन्युअल रूप से एक सरल कंटेनर लागू किया जा सकता है।
use std::collections::HashMap;
// डिपेंडेंसी फैक्ट्रियों के लिए ट्रेटtrait Factory<T> { fn create(&self) -> T;}
// सरल डिपेंडेंसी कंटेनरstruct Container { factories: HashMap<String, Box<dyn std::any::Any>>,}
impl Container { fn new() -> Self { Container { factories: HashMap::new(), } }
fn register<T: 'static>(&mut self, name: &str, factory: Box<dyn Factory<T>>) { self.factories.insert(name.to_string(), Box::new(factory)); }
fn resolve<T: 'static>(&self, name: &str) -> Option<T> { self.factories.get(name).and_then(|f|