मैं अक्सर अपनी परियोजनाओं में "निर्भरता इंजेक्शन" पैटर्न का उपयोग करता हूं। सी ++ में कच्चे पॉइंटर्स के चारों ओर गुजरकर इसे कार्यान्वित करना सबसे आसान है, लेकिन अब सी ++ 11 के साथ, उच्च-स्तरीय कोड में सबकुछ स्मार्ट पॉइंटर्स के साथ किया जाना चाहिए। लेकिन इस मामले के लिए सबसे अच्छा अभ्यास क्या है? प्रदर्शन महत्वपूर्ण नहीं है, अब एक साफ और समझने योग्य कोड मेरे लिए अधिक मायने रखता है।कच्चे पॉइंटर्स के बिना सी ++ 11 में निर्भरता इंजेक्शन
मुझे एक सरलीकृत उदाहरण दिखाएं। हमारे पास एक एल्गोरिदम है जो अंदर की दूरी गणना का उपयोग करता है। हम इस गणना को विभिन्न दूरी मीट्रिक (यूक्लिडियन, मैनहट्टन इत्यादि) के साथ प्रतिस्थापित करने में सक्षम होना चाहते हैं।
SomeAlgorithm algorithmWithEuclidean(new EuclideanDistanceCalculator());
SomeAlgorithm algorithmWithManhattan(new ManhattanDistanceCalculator());
लेकिन स्मार्ट संकेत के साथ मैनुअल new
और delete
से बचने के लिए: हमारा लक्ष्य कहने के लिए कुछ तरह सक्षम हो किया जा सके। यह कच्चे संकेत के साथ एक संभव कार्यान्वयन है:
class DistanceCalculator {
public:
virtual double distance(Point p1, Point p2) = 0;
};
class EuclideanDistanceCalculator {
public:
virtual double distance(Point p1, Point p2) {
return sqrt(...);
}
};
class ManhattanDistanceCalculator {
public:
virtual double distance(Point p1, Point p2) {
return ...;
}
};
class SomeAlgorithm {
DistanceCalculator* distanceCalculator;
public:
SomeAlgorithm(DistanceCalculator* distanceCalculator_)
: distanceCalculator(distanceCalculator_) {}
double calculateComplicated() {
...
double dist = distanceCalculator->distance(p1, p2);
...
}
~SomeAlgorithm(){
delete distanceCalculator;
}
};
मान लेते हैं कि नकल वास्तव में कोई मुद्दा नहीं है, और अगर हम बहुरूपता जरूरत नहीं थी हम सिर्फ DistanceCalculator
SomeAlgorithm
के निर्माता के लिए मूल्य द्वारा नकल से होकर गुजरेगा ()। लेकिन चूंकि हमें अलग-अलग व्युत्पन्न उदाहरणों (स्लाइसिंग के बिना) में पारित करने में सक्षम होने की आवश्यकता है, इसलिए पैरामीटर या तो कच्चे सूचक, संदर्भ या स्मार्ट पॉइंटर होना चाहिए।
एक समाधान जो दिमाग में आता है उसे संदर्भ-से-कॉन्स द्वारा पास करना है और std::unique_ptr<DistanceCalculator>
सदस्य चर में इसे समाहित करना है। फिर कॉल होगा:
SomeAlgorithm algorithmWithEuclidean(EuclideanDistance());
लेकिन इस ढेर-आवंटित अस्थायी वस्तु (rvalue-संदर्भ?) इस लाइन के बाद विलुप्त हो जाएगा। तो हमें पास-दर-मूल्य की तरह इसे बनाने के लिए कुछ प्रतिलिपि की आवश्यकता होगी। लेकिन चूंकि हम रनटाइम प्रकार को नहीं जानते हैं, इसलिए हम आसानी से हमारी प्रतिलिपि नहीं बना सकते हैं।
हम कन्स्ट्रक्टर पैरामीटर के रूप में एक स्मार्ट सूचक का भी उपयोग कर सकते हैं। चूंकि स्वामित्व के साथ कोई समस्या नहीं है (DistanceCalculator
का स्वामित्व SomeAlgorithm
होगा) हमें std::unique_ptr
का उपयोग करना चाहिए। क्या मुझे वास्तव में unique_ptr
के साथ ऐसे सभी कन्स्ट्रक्टर पैरामीटर को प्रतिस्थापित करना चाहिए? ऐसा लगता है कि पठनीयता कम हो जाती है। इसके अलावा SomeAlgorithm
के उपयोगकर्ता एक अजीब तरीके से निर्माण करना होगा:
SomeAlgorithm algorithmWithEuclidean(std::unique_ptr<DistanceCalculator>(new EuclideanDistance()));
या मैं किसी तरह से नई चाल अर्थ विज्ञान (& &, std :: चाल) इस्तेमाल करना चाहिए?
यह एक बहुत ही मानक समस्या प्रतीत होता है, इसे लागू करने के लिए कुछ संक्षिप्त तरीका होना चाहिए।
SomeAlgorithm(std::function<double(Point,Point)> distanceCalculator_)
प्रकार मिट मंगलाचरण वस्तु:
आपको यह प्रश्न दिलचस्प भी मिल सकता है: http://stackoverflow.com/questions/4469304/dependency-injection-framework-for-c –