C++ में डिज़ाइन पैटर्न उदाहरणों के साथ: A से Z तक
\n\nडिज़ाइन पैटर्न (design patterns) सॉफ्टवेयर विकास के दौरान उत्पन्न होने वाली सामान्य समस्याओं के सिद्ध समाधान हैं। C++ के लिए ये पैटर्न विशेष रूप से महत्वपूर्ण हैं, क्योंकि यह भाषा ऑब्जेक्ट-ओरिएंटेड, जेनेरिक और निम्न-स्तरीय प्रोग्रामिंग को जोड़ती है। इस लेख में, हम कोड उदाहरणों के साथ C++ में प्रमुख डिज़ाइन पैटर्न पर चर्चा करेंगे, जो आपको अधिक लचीला, पुन: प्रयोज्य और रखरखाव योग्य कोड लिखने में मदद करेंगे।
\n\nहम GoF (Gang of Four) वर्गीकरण के अनुसार तीन मुख्य श्रेणियों के पैटर्न पर विचार करेंगे: क्रिएशनल, स्ट्रक्चरल और बिहेवियरल। प्रत्येक पैटर्न को C++ में एक वास्तविक उदाहरण के साथ समझाया जाएगा।
\n\n1. क्रिएशनल पैटर्न (Creational Patterns)
\n\nक्रिएशनल पैटर्न ऑब्जेक्ट निर्माण की प्रक्रिया को अमूर्त करते हैं, जिससे सिस्टम इस बात से स्वतंत्र हो जाता है कि ऑब्जेक्ट कैसे बनाए, संयोजित और प्रस्तुत किए जाते हैं।
\n\n1.1. Singleton (एकल)
\n\nSingleton यह सुनिश्चित करता है कि एक क्लास का केवल एक इंस्टेंस हो, और उस तक वैश्विक पहुँच प्रदान करता है। C++ में इसे अक्सर स्टैटिक लोकल ऑब्जेक्ट (C++11 से thread-safe) के माध्यम से कार्यान्वित किया जाता है।
\n\nclass Logger {\npublic:\n static Logger& getInstance() {\n static Logger instance; // thread-safe इनिशियलाइज़ेशन\n return instance;\n }\n\n void log(const std::string& message) {\n std::cout << "[LOG] " << message << std::endl;\n }\n\nprivate:\n Logger() = default;\n Logger(const Logger&) = delete;\n Logger& operator=(const Logger&) = delete;\n};\n\n// उपयोग\nint main() {\n Logger::getInstance().log("एप्लिकेशन शुरू हुआ");\n return 0;\n}\n\nकब उपयोग करें: कॉन्फ़िगरेशन प्रबंधन, थ्रेड पूल, लॉगिंग सिस्टम।
\n\n1.2. Factory Method (फ़ैक्टरी विधि)
\n\nFactory Method ऑब्जेक्ट बनाने के लिए एक इंटरफ़ेस परिभाषित करता है, लेकिन उपवर्गों को यह तय करने देता है कि किस क्लास को इंस्टेंशिएट करना है।
\n\nclass Product {\npublic:\n virtual void use() = 0;\n virtual ~Product() = default;\n};\n\nclass ConcreteProductA : public Product {\npublic:\n void use() override { std::cout << "उत्पाद A" << std::endl; }\n};\n\nclass ConcreteProductB : public Product {\npublic:\n void use() override { std::cout << "उत्पाद B" << std::endl; }\n};\n\nclass Creator {\npublic:\n virtual Product* createProduct() = 0;\n void someOperation() {\n Product* p = createProduct();\n p->use();\n delete p;\n }\n virtual ~Creator() = default;\n};\n\nclass CreatorA : public Creator {\npublic:\n Product* createProduct() override { return new ConcreteProductA(); }\n};\n\nclass CreatorB : public Creator {\npublic:\n Product* createProduct() override { return new ConcreteProductB(); }\n};\n\nकब उपयोग करें: जब क्लास को यह नहीं पता होता कि उसे किन उपवर्गों के ऑब्जेक्ट बनाने हैं।
\n\n2. स्ट्रक्चरल पैटर्न (Structural Patterns)
\n\nस्ट्रक्चरल पैटर्न वर्णन करते हैं कि कैसे क्लास और ऑब्जेक्ट को बड़ी संरचनाओं में संयोजित किया जा सकता है, जबकि लचीलापन और दक्षता बनी रहे।
\n\n2.1. Adapter (अनुकूलक)
\n\nAdapter असंगत इंटरफ़ेस वाले ऑब्जेक्ट को एक साथ काम करने की अनुमति देता है। C++ में इसे अक्सर इनहेरिटेंस या कम्पोज़िशन के माध्यम से कार्यान्वित किया जाता है।
\n\n// लक्ष्य इंटरफ़ेस\nclass Target {\npublic:\n virtual void request() const {\n std::cout << "सामान्य अनुरोध" << std::endl;\n }\n virtual ~Target() = default;\n};\n\n// अनुकूलनीय क्लास\nclass Adaptee {\npublic:\n void specificRequest() const {\n std::cout << "विशिष्ट अनुरोध" << std::endl;\n }\n};\n\n// अनुकूलक (कम्पोज़िशन के माध्यम से)\nclass Adapter : public Target {\nprivate:\n Adaptee* adaptee_;\npublic:\n Adapter(Adaptee* a) : adaptee_(a) {}\n void request() const override {\n adaptee_->specificRequest();\n }\n};