जब साफ, रखरखाव योग्य और कुशल कोड लिखने की बात आती है, तो डिज़ाइन पैटर्न सॉफ्टवेयर विकास की दुनिया में महत्वपूर्ण भूमिका निभाते हैं। डिज़ाइन पैटर्न सामान्य समस्याओं के लिए पुन: प्रयोज्य समाधान हैं जिनका डेवलपर्स को सॉफ़्टवेयर सिस्टम डिज़ाइन और निर्माण करते समय सामना करना पड़ता है। वे विशिष्ट चुनौतियों को हल करने के लिए एक संरचित दृष्टिकोण प्रदान करते हैं, जिससे कोड बनाना आसान हो जाता है जो न केवल मजबूत होता है बल्कि समझने और बनाए रखने में भी आसान होता है।
ऑब्जेक्ट-ओरिएंटेड प्रोग्रामिंग (ओओपी ) में, डिज़ाइन पैटर्न आपके कोड को इस तरह से संरचित करने के लिए दिशानिर्देश के रूप में कार्य करते हैं जो लचीलेपन, पुन: प्रयोज्य और स्केलेबिलिटी को बढ़ावा देता है। वे सर्वोत्तम प्रथाओं और डिजाइन सिद्धांतों को समाहित करते हैं जो विकसित हुए हैं और सिद्ध समाधानों में बदल गए हैं।
डिज़ाइन पैटर्न को तीन मुख्य समूहों में वर्गीकृत किया जा सकता है:
रचनात्मक पैटर्न: ये पैटर्न वस्तु निर्माण तंत्र पर ध्यान केंद्रित करते हैं, स्थिति के लिए उपयुक्त तरीके से वस्तुओं को बनाने की कोशिश करते हैं। वे इन्स्टेन्शियेशन प्रक्रिया को अमूर्त बनाते हैं, जिससे यह अधिक लचीला और सिस्टम से स्वतंत्र हो जाता है।
संरचनात्मक पैटर्न: संरचनात्मक पैटर्न वस्तु संरचना से निपटते हैं, बड़ी, अधिक जटिल संरचनाएं बनाने के लिए वस्तुओं के बीच संबंध बनाते हैं। वे यह परिभाषित करने में मदद करते हैं कि नई संरचनाएं बनाने और नई कार्यक्षमता प्रदान करने के लिए वस्तुओं और कक्षाओं को कैसे जोड़ा जा सकता है।
व्यवहार पैटर्न: व्यवहार पैटर्न वस्तुओं के बीच संचार से संबंधित हैं, यह परिभाषित करते हैं कि वे कैसे बातचीत करते हैं और जिम्मेदारियों को वितरित करते हैं। ये पैटर्न आपको ऐसे सिस्टम डिज़ाइन करने में मदद करते हैं जहां ऑब्जेक्ट अधिक लचीले और कुशल तरीके से सहयोग करते हैं।
यहां प्रत्येक श्रेणी में कुछ सामान्य डिज़ाइन पैटर्न की सूची दी गई है:
पर्यवेक्षक पैटर्न: वस्तुओं के बीच एक-से-अनेक निर्भरता को परिभाषित करता है, इसलिए जब एक वस्तु स्थिति बदलती है, तो उसके सभी आश्रितों को स्वचालित रूप से सूचित और अद्यतन किया जाता है।
रणनीति पैटर्न: एल्गोरिदम के एक परिवार को परिभाषित करता है, प्रत्येक को समाहित करता है, और उन्हें विनिमेय बनाता है।
कमांड पैटर्न: एक अनुरोध को एक ऑब्जेक्ट के रूप में एनकैप्सुलेट करता है, जिससे कतारों, अनुरोधों और संचालन के साथ ग्राहकों के पैरामीटराइजेशन की अनुमति मिलती है।
राज्य पैटर्न: किसी वस्तु की आंतरिक स्थिति बदलने पर उसके व्यवहार को बदलने की अनुमति देता है, व्यवहार को अलग-अलग वर्गों में लपेटता है।
जिम्मेदारी पैटर्न की श्रृंखला: अनुरोध को हैंडलर की श्रृंखला के साथ पास करती है, जिससे प्रत्येक हैंडलर को अनुरोध को संसाधित करने या श्रृंखला में अगले हैंडलर को भेजने का निर्णय लेने की अनुमति मिलती है।
विज़िटर पैटर्न: यह किसी ऑब्जेक्ट संरचना के तत्वों पर किए जाने वाले एक ऑपरेशन का प्रतिनिधित्व करता है, जो आपको तत्वों की कक्षाओं को बदले बिना नए ऑपरेशन को परिभाषित करने में सक्षम बनाता है।
इस ब्लॉग में, हम इनमें से प्रत्येक डिज़ाइन पैटर्न पर गहराई से विचार करेंगे, स्पष्टीकरण, वास्तविक दुनिया के उपयोग के मामले और जावास्क्रिप्ट कोड उदाहरण प्रदान करेंगे ताकि आपको उन्हें समझने और अपनी परियोजनाओं में प्रभावी ढंग से लागू करने में मदद मिल सके।
सिंगलटन पैटर्न एक सृजनात्मक डिज़ाइन पैटर्न है जो यह सुनिश्चित करता है कि एक वर्ग के पास केवल एक उदाहरण हो और उस उदाहरण तक पहुंच का एक वैश्विक बिंदु प्रदान करता हो। यह पैटर्न विशेष रूप से तब उपयोगी होता है जब आप अपने एप्लिकेशन में किसी क्लास के इंस्टेंस की संख्या को सीमित करना चाहते हैं और एकल साझा इंस्टेंस तक पहुंच को नियंत्रित करना चाहते हैं।
जावास्क्रिप्ट में, भाषा के लचीलेपन के कारण सिंगलटन पैटर्न को लागू करना अपेक्षाकृत सरल है। आइए जावास्क्रिप्ट में सिंगलटन बनाने के तरीके का एक सरल उदाहरण देखें।
// Singleton instance let instance = null;
class Singleton { constructor() { if (!instance) { instance = this; // Your initialization code here } else { return instance; } } // Your methods and properties here }// Usage const singletonA = new Singleton(); const singletonB = new Singleton(); console.log(singletonA === singletonB); // Output: true (both variables reference the same instance)
इस उदाहरण में, हम एक कंस्ट्रक्टर के साथ एक सिंगलटन क्लास बनाते हैं जो जाँचता है कि कोई इंस्टेंस पहले से मौजूद है या नहीं। यदि कोई इंस्टेंस मौजूद नहीं है, तो यह एक बनाता है और इसे इंस्टेंस वेरिएबल को असाइन करता है। कंस्ट्रक्टर को बाद में कॉल करने से मौजूदा इंस्टेंस वापस आ जाता है, जिससे यह सुनिश्चित हो जाता है कि सिंगलटन क्लास का केवल एक ही इंस्टेंस है।
सिंगलटन पैटर्न विभिन्न परिदृश्यों में उपयोगी है, जिनमें शामिल हैं:
हालाँकि सिंगलटन पैटर्न फायदेमंद हो सकता है, लेकिन इसका विवेकपूर्ण तरीके से उपयोग करना आवश्यक है। सिंगलटन पैटर्न का अत्यधिक उपयोग करने से कोड और वैश्विक स्थिति कसकर युग्मित हो सकती है, जिससे आपके एप्लिकेशन को बनाए रखना और परीक्षण करना कठिन हो सकता है। इसलिए, पेशेवरों और विपक्षों को तौलना और उस पैटर्न को लागू करना महत्वपूर्ण है जहां यह वास्तव में आपके कोडबेस में मूल्य जोड़ता है।
फ़ैक्टरी पैटर्न और एब्सट्रैक्ट फ़ैक्टरी पैटर्न रचनात्मक डिज़ाइन पैटर्न हैं जो वस्तुओं के निर्माण से संबंधित हैं, लेकिन वे अलग-अलग तरीकों से ऐसा करते हैं और अलग-अलग उद्देश्यों की पूर्ति करते हैं। आइए इनमें से प्रत्येक पैटर्न का पता लगाएं और देखें कि उन्हें जावास्क्रिप्ट में कैसे लागू किया जा सकता है।
फ़ैक्टरी पैटर्न एक रचनात्मक पैटर्न है जो ऑब्जेक्ट बनाने के लिए एक इंटरफ़ेस प्रदान करता है लेकिन उपवर्गों को बनाए जाने वाले ऑब्जेक्ट के प्रकार को बदलने की अनुमति देता है। यह ऑब्जेक्ट निर्माण प्रक्रिया को समाहित करता है, जिससे यह अधिक लचीला हो जाता है और क्लाइंट कोड से अलग हो जाता है।
// Product class class Product { constructor(name) { this.name = name; } }
// Factory for creating products class ProductFactory { createProduct(name) { return new Product(name); } }// Usage const factory = new ProductFactory(); const productA = factory.createProduct('Product A'); const productB = factory.createProduct('Product B');console.log(productA.name); // Output: 'Product A' console.log(productB.name); // Output: 'Product B'
इस उदाहरण में, ProductFactory उत्पाद वर्ग के उदाहरण बनाने के लिए जिम्मेदार है। यह निर्माण प्रक्रिया को सारगर्भित करता है, जिससे आप फ़ैक्टरी का विस्तार करके विभिन्न प्रकार के उत्पाद बना सकते हैं।
एब्सट्रैक्ट फ़ैक्टरी पैटर्न एक अन्य रचनात्मक पैटर्न है जो संबंधित या आश्रित वस्तुओं के परिवारों को उनके ठोस वर्गों को निर्दिष्ट किए बिना बनाने के लिए एक इंटरफ़ेस प्रदान करता है। यह आपको वस्तुओं के सेट बनाने की अनुमति देता है जो सामंजस्यपूर्ण रूप से एक साथ काम करते हैं।
// Abstract Product classes class Button { render() {} }
class Checkbox { render() {} }// Concrete Product classes class MacButton extends Button { render() { return 'Render Mac button'; } }class MacCheckbox extends Checkbox { render() { return 'Render Mac checkbox'; } }class WindowsButton extends Button { render() { return 'Render Windows button'; } }class WindowsCheckbox extends Checkbox { render() { return 'Render Windows checkbox'; } }// Abstract Factory interface class GUIFactory { createButton() {} createCheckbox() {} }// Concrete Factories class MacFactory extends GUIFactory { createButton() { return new MacButton(); } createCheckbox() { return new MacCheckbox(); } }class WindowsFactory extends GUIFactory { createButton() { return new WindowsButton(); } createCheckbox() { return new WindowsCheckbox(); } }// Usage function createUI(factory) { const button = factory.createButton(); const checkbox = factory.createCheckbox(); return { button, checkbox }; }const macUI = createUI(new MacFactory()); console.log(macUI.button.render()); // Output: 'Render Mac button' console.log(macUI.checkbox.render()); // Output: 'Render Mac checkbox'const windowsUI = createUI(new WindowsFactory()); console.log(windowsUI.button.render()); // Output: 'Render Windows button' console.log(windowsUI.checkbox.render()); // Output: 'Render Windows checkbox'
इस उदाहरण में, हमारे पास दो ठोस फ़ैक्टरियाँ हैं, MacFactory और WindowsFactory, प्रत्येक अपने संबंधित प्लेटफ़ॉर्म के लिए संबंधित UI घटकों (बटन और चेकबॉक्स) का एक सेट बनाने में सक्षम हैं। क्रिएटयूआई फ़ंक्शन आपको उपयुक्त फ़ैक्टरी का उपयोग करके एक विशिष्ट प्लेटफ़ॉर्म के लिए एक समेकित यूआई बनाने की अनुमति देता है।
कब किस पैटर्न का उपयोग करें:
बिल्डर पैटर्न एक रचनात्मक डिज़ाइन पैटर्न है जो एक जटिल वस्तु के निर्माण को उसके प्रतिनिधित्व से अलग करता है, जिससे एक ही निर्माण प्रक्रिया को अलग-अलग प्रतिनिधित्व बनाने की अनुमति मिलती है। यह पैटर्न विशेष रूप से तब उपयोगी होता है जब आपके पास बड़ी संख्या में गुणों वाला ऑब्जेक्ट होता है, और आप लचीलेपन को बनाए रखते हुए उदाहरणों के निर्माण को सरल बनाना चाहते हैं।
जावास्क्रिप्ट में, बिल्डर पैटर्न को अक्सर बिल्डर क्लास या ऑब्जेक्ट का उपयोग करके कार्यान्वित किया जाता है जो जटिल ऑब्जेक्ट के चरण-दर-चरण निर्माण का मार्गदर्शन करता है। आइए यह समझने के लिए एक उदाहरण देखें कि यह कैसे काम करता है।
// Product class with multiple properties class Product { constructor() { this.name = ''; this.price = 0; this.color = 'white'; // ... other properties }
// Additional methods can be defined here }// Builder for creating Product instances class ProductBuilder { constructor() { this.product = new Product(); } setName(name) { this.product.name = name; return this; // Return the builder for method chaining } setPrice(price) { this.product.price = price; return this; } setColor(color) { this.product.color = color; return this; } // Other methods to set additional properties build() { return this.product; // Return the fully constructed product } }// Usage const builder = new ProductBuilder();const productA = builder .setName('Product A') .setPrice(99.99) .setColor('blue') .build();const productB = builder .setName('Product B') .setPrice(49.99) .build();console.log(productA); console.log(productB);
इस उदाहरण में, हमारे पास एकाधिक गुणों वाला एक उत्पाद वर्ग है। ProductBuilder वर्ग प्रत्येक संपत्ति को चरण दर चरण सेट करने के तरीके प्रदान करके उत्पाद के उदाहरण बनाने में मदद करता है। मेथड चेनिंग आपको कई गुणों को धाराप्रवाह और पठनीय तरीके से सेट करने की अनुमति देता है। अंत में, बिल्ड विधि पूरी तरह से निर्मित उत्पाद उदाहरण लौटाती है।
बिल्डर पैटर्न विभिन्न परिदृश्यों में फायदेमंद है, जिनमें शामिल हैं:
जबकि बिल्डर पैटर्न कई फायदे प्रदान करता है, यह ध्यान रखना महत्वपूर्ण है कि यह आपके कोडबेस में जटिलता जोड़ता है, खासकर यदि निर्मित की जा रही वस्तुएं अपेक्षाकृत सरल हैं। इसलिए, यह मूल्यांकन करना आवश्यक है कि बिल्डर द्वारा पेश की गई जटिलता आपके विशिष्ट उपयोग के मामले के लिए उचित है या नहीं।
प्रोटोटाइप पैटर्न एक रचनात्मक डिज़ाइन पैटर्न है जो आपको मौजूदा ऑब्जेक्ट की प्रतिलिपि बनाकर नई ऑब्जेक्ट बनाने की अनुमति देता है, जिसे प्रोटोटाइप के रूप में जाना जाता है। यह बनाई जाने वाली वस्तु के सटीक वर्ग को निर्दिष्ट किए बिना वस्तुओं के निर्माण को बढ़ावा देता है। यह पैटर्न विशेष रूप से तब उपयोगी होता है जब आप जटिल वस्तुओं के उदाहरण कुशलतापूर्वक बनाना चाहते हैं।
जावास्क्रिप्ट में, प्रोटोटाइप पैटर्न अंतर्निहित prototype
प्रॉपर्टी और Object.create()
विधि से निकटता से संबंधित है। आइए जानें कि जावास्क्रिप्ट में प्रोटोटाइप पैटर्न को कैसे कार्यान्वित और उपयोग किया जाए।
// Prototype object const vehiclePrototype = { init(make, model) { this.make = make; this.model = model; }, getDetails() { return `${this.make} ${this.model}`; }, };
// Create new instances using the prototype const car1 = Object.create(vehiclePrototype); car1.init('Toyota', 'Camry');const car2 = Object.create(vehiclePrototype); car2.init('Honda', 'Civic');console.log(car1.getDetails()); // Output: 'Toyota Camry' console.log(car2.getDetails()); // Output: 'Honda Civic'
इस उदाहरण में, हम सभी वाहनों के लिए सामान्य तरीकों और गुणों के साथ एक vehiclePrototype
ऑब्जेक्ट को परिभाषित करते हैं। हम इस प्रोटोटाइप के आधार पर नए इंस्टेंस (car1 और car2) बनाने के लिए Object.create()
का उपयोग करते हैं। ये उदाहरण प्रोटोटाइप से गुणों और विधियों को प्राप्त करते हैं, जिससे आप साझा व्यवहार के साथ कुशलतापूर्वक नई ऑब्जेक्ट बना सकते हैं।
प्रोटोटाइप पैटर्न विभिन्न परिदृश्यों में मूल्यवान है, जिनमें शामिल हैं:
जबकि प्रोटोटाइप पैटर्न उपयोगी है, इसमें कुछ विचार हैं:
ऑब्जेक्ट पूल पैटर्न एक रचनात्मक डिज़ाइन पैटर्न है जो ऑब्जेक्ट निर्माण और विनाश के ओवरहेड को कम करने के लिए पुन: प्रयोज्य वस्तुओं के एक पूल का प्रबंधन करता है। यह विशेष रूप से तब उपयोगी होता है जब वस्तुओं को बनाना और नष्ट करना महंगा या संसाधन-गहन होता है। ऑब्जेक्ट पूल पैटर्न स्क्रैच से नई वस्तुओं को बनाने के बजाय रीसाइक्लिंग और पुन: उपयोग करके प्रदर्शन और संसाधन उपयोग को बेहतर बनाने में मदद करता है।
जावास्क्रिप्ट में, आप सरणियों या कस्टम पूल प्रबंधन कक्षाओं का उपयोग करके ऑब्जेक्ट पूल पैटर्न को कार्यान्वित कर सकते हैं। आइए जानें कि यह पैटर्न एक सरल उदाहरण के साथ कैसे काम करता है।
class ObjectPool { constructor(maxSize) { this.maxSize = maxSize; this.pool = []; }
create() { if (this.pool.length < this.maxSize) { // Create a new object and add it to the pool const obj = { /* Your object initialization code here */ }; this.pool.push(obj); return obj; } else { // Pool is full, cannot create more objects console.log('Pool is full. Cannot create more objects.'); return null; } } reuse() { if (this.pool.length > 0) { // Reuse an object from the pool return this.pool.pop(); } else { // Pool is empty, no objects available for reuse console.log('Pool is empty. No objects available for reuse.'); return null; } } release(obj) { // Release an object back to the pool for reuse this.pool.push(obj); } }// Usage const pool = new ObjectPool(5); // Create a pool with a maximum size of 5 objectsconst obj1 = pool.create(); const obj2 = pool.create(); const obj3 = pool.create();pool.release(obj2); // Release obj2 back to the pool for reuseconst obj4 = pool.reuse(); // Reuse an object from the pool (obj2)
इस उदाहरण में, हम एक ऑब्जेक्टपूल क्लास बनाते हैं जो ऑब्जेक्ट्स के पूल का प्रबंधन करता है। जब पूल भरा नहीं होता है तो क्रिएट विधि नई ऑब्जेक्ट बनाती है, पुन: उपयोग विधि पुन: उपयोग के लिए पूल से एक ऑब्जेक्ट को पुनर्प्राप्त करती है, और रिलीज़ विधि भविष्य में उपयोग के लिए एक ऑब्जेक्ट को पूल में लौटाती है।
ऑब्जेक्ट पूल पैटर्न विभिन्न परिदृश्यों में उपयोगी है, जिनमें शामिल हैं:
जबकि ऑब्जेक्ट पूल पैटर्न प्रदर्शन लाभ प्रदान करता है, निम्नलिखित पर विचार करना महत्वपूर्ण है:
एडॉप्टर पैटर्न एक संरचनात्मक डिज़ाइन पैटर्न है जो असंगत इंटरफेस वाली वस्तुओं को एक साथ काम करने की अनुमति देता है। यह दो असंगत इंटरफेस के बीच एक पुल के रूप में कार्य करता है, जो उन्हें उनके स्रोत कोड को बदले बिना संगत बनाता है। यह पैटर्न विशेष रूप से तब उपयोगी होता है जब आपको मौजूदा कोड को एकीकृत करने या उपयोग करने की आवश्यकता होती है जो आपके एप्लिकेशन की आवश्यकताओं के साथ बिल्कुल फिट नहीं होता है।
जावास्क्रिप्ट में, एडेप्टर पैटर्न को उन कक्षाओं या फ़ंक्शंस का उपयोग करके कार्यान्वित किया जा सकता है जो असंगत इंटरफ़ेस को लपेटते या अनुकूलित करते हैं। आइए एक व्यावहारिक उदाहरण के साथ जानें कि जावास्क्रिप्ट में एडेप्टर पैटर्न को कैसे कार्यान्वित और उपयोग किया जाए।
मान लीजिए कि आपके पास OldSystem
नाम की एक मौजूदा क्लास है, जिसका एक तरीका legacyRequest
:
class OldSystem { legacyRequest() { return 'Data from the legacy system'; } }
अब, आप अपने आधुनिक एप्लिकेशन में इस विरासत प्रणाली का उपयोग करना चाहते हैं जो एक अलग इंटरफ़ेस की अपेक्षा करता है। आप इस तरह एक एडॉप्टर क्लास या फ़ंक्शन बना सकते हैं:
class Adapter { constructor(oldSystem) { this.oldSystem = oldSystem; }
newRequest() { const legacyData = this.oldSystem.legacyRequest(); // Adapt the data or perform any necessary transformations return `Adapted: ${legacyData}`; } }
अब, आप लीगेसी सिस्टम को अपने आधुनिक एप्लिकेशन के साथ संगत बनाने के लिए एडाप्टर क्लास का उपयोग कर सकते हैं:
const oldSystem = new OldSystem(); const adapter = new Adapter(oldSystem);
const result = adapter.newRequest(); console.log(result); // Output: 'Adapted: Data from the legacy system'
इस उदाहरण में, एडॉप्टर क्लास OldSystem को लपेटता है और एक नया इंटरफ़ेस, newRequest प्रदान करता है, जो आपके आधुनिक एप्लिकेशन के साथ संगत है।
एडॉप्टर पैटर्न विभिन्न परिदृश्यों में मूल्यवान है, जिनमें शामिल हैं:
जबकि एडॉप्टर पैटर्न लचीलापन और अनुकूलता प्रदान करता है, कुछ बिंदुओं पर विचार करना आवश्यक है:
डेकोरेटर पैटर्न एक संरचनात्मक डिज़ाइन पैटर्न है जो आपको वस्तुओं के मौजूदा कोड को बदले बिना गतिशील रूप से नए व्यवहार या जिम्मेदारियाँ जोड़ने की अनुमति देता है। यह वस्तुओं को डेकोरेटर वस्तुओं के साथ लपेटकर उनकी कार्यक्षमता बढ़ाने का एक शक्तिशाली तरीका है। यह पैटर्न "विस्तार के लिए खुला है, लेकिन संशोधन के लिए बंद है" के सिद्धांत को बढ़ावा देता है, जिससे वस्तुओं के मूल कार्यान्वयन को बदले बिना नई सुविधाओं को जोड़ना आसान हो जाता है।
जावास्क्रिप्ट में, डेकोरेटर पैटर्न को कक्षाओं और ऑब्जेक्ट संरचना का उपयोग करके कार्यान्वित किया जा सकता है। आइए एक व्यावहारिक उदाहरण के साथ जानें कि जावास्क्रिप्ट में डेकोरेटर पैटर्न को कैसे कार्यान्वित और उपयोग किया जाए।
मान लीजिए आपके पास बेस क्लास Coffee
है:
class Coffee { cost() { return 5; // Base cost of a regular coffee } } Now, you want to add decorators to your coffee to customize it with additional options, such as milk and sugar:
javascript Copy code class MilkDecorator { constructor(coffee) { this.coffee = coffee; } cost() { return this.coffee.cost() + 2; // Adding the cost of milk } }class SugarDecorator { constructor(coffee) { this.coffee = coffee; } cost() { return this.coffee.cost() + 1; // Adding the cost of sugar } }
फिर आप इस तरह से सजाए गए कॉफ़ी के उदाहरण बना सकते हैं:
const regularCoffee = new Coffee(); const coffeeWithMilk = new MilkDecorator(regularCoffee); const coffeeWithMilkAndSugar = new SugarDecorator(coffeeWithMilk);
console.log(regularCoffee.cost()); // Output: 5 console.log(coffeeWithMilk.cost()); // Output: 7 console.log(coffeeWithMilkAndSugar.cost()); // Output: 8
इस उदाहरण में, हमारे पास कॉफ़ी क्लास है जो बेस कॉफ़ी का प्रतिनिधित्व करती है। मिल्कडेकोरेटर और शुगरडेकोरेटर वर्ग ऐसे डेकोरेटर हैं जो एक कॉफी वस्तु को लपेटते हैं और आधार लागत में क्रमशः दूध और चीनी की लागत जोड़ते हैं।
डेकोरेटर पैटर्न विभिन्न परिदृश्यों में मूल्यवान है, जिनमें शामिल हैं:
जबकि डेकोरेटर पैटर्न बहुमुखी है, कुछ बातों को ध्यान में रखना महत्वपूर्ण है:
प्रॉक्सी पैटर्न एक संरचनात्मक डिज़ाइन पैटर्न है जो किसी अन्य ऑब्जेक्ट तक पहुंच को नियंत्रित करने के लिए एक सरोगेट या प्लेसहोल्डर प्रदान करता है। यह लक्ष्य वस्तु के चारों ओर एक मध्यस्थ या आवरण के रूप में कार्य करता है, जो आपको अतिरिक्त व्यवहार जोड़ने, पहुंच को नियंत्रित करने या वस्तु निर्माण में देरी करने की अनुमति देता है। प्रॉक्सी पैटर्न विभिन्न परिदृश्यों में उपयोगी है, जैसे आलसी लोडिंग, एक्सेस कंट्रोल और लॉगिंग लागू करना।
जावास्क्रिप्ट में, अंतर्निहित Proxy
ऑब्जेक्ट का उपयोग करके प्रॉक्सी बनाई जा सकती है। आइए व्यावहारिक उदाहरणों के साथ जावास्क्रिप्ट में प्रॉक्सी पैटर्न को लागू करने और उपयोग करने का तरीका जानें।
मान लीजिए कि आपके पास एक संसाधन-गहन वस्तु है जिसे आप केवल जरूरत पड़ने पर ही लोड करना चाहते हैं। आप आलसी लोडिंग प्राप्त करने के लिए प्रॉक्सी का उपयोग कर सकते हैं:
class ExpensiveResource { constructor() { console.log('Creating an expensive resource...'); }
fetchData() { console.log('Fetching data...'); } }class LazyResourceProxy { constructor() { this.resource = null; } fetchData() { if (!this.resource) { this.resource = new ExpensiveResource(); } this.resource.fetchData(); } }// Usage const lazyResource = new LazyResourceProxy(); // The actual resource is created and data is fetched only when needed lazyResource.fetchData();
इस उदाहरण में, LazyResourceProxy एक्सपेंसिवरिसोर्स के लिए सरोगेट के रूप में कार्य करता है, वास्तविक संसाधन केवल तभी बनाता है जब पहली बार फ़ेचडेटा विधि को कॉल किया जाता है।
आप वस्तुओं और उनकी संपत्तियों तक पहुंच को नियंत्रित करने के लिए प्रॉक्सी का भी उपयोग कर सकते हैं:
const user = { username: 'john_doe', password: 'secret123', };
const userProxy = new Proxy(user, { get(target, property) { if (property === 'password') { throw new Error('Access denied to password.'); } return target[property]; }, });console.log(userProxy.username); // Output: 'john_doe' console.log(userProxy.password); // Throws an error: 'Access denied to password.'
इस उदाहरण में, प्रॉक्सी गेट ऑपरेशन को रोकता है और पासवर्ड प्रॉपर्टी तक पहुंच को प्रतिबंधित करता है।
प्रॉक्सी पैटर्न विभिन्न परिदृश्यों में मूल्यवान है, जिनमें शामिल हैं:
प्रॉक्सी पैटर्न का उपयोग करते समय, निम्नलिखित बातों को ध्यान में रखें:
समग्र पैटर्न एक संरचनात्मक डिज़ाइन पैटर्न है जो आपको आंशिक-संपूर्ण पदानुक्रम का प्रतिनिधित्व करने के लिए वस्तुओं को पेड़ जैसी संरचनाओं में संयोजित करने की अनुमति देता है। यह ग्राहकों को व्यक्तिगत वस्तुओं और वस्तुओं की रचनाओं के साथ समान रूप से व्यवहार करने की सुविधा देता है। समग्र पैटर्न विशेष रूप से तब उपयोगी होता है जब आपको एक सुसंगत इंटरफ़ेस बनाए रखते हुए छोटी, संबंधित वस्तुओं से बनी जटिल संरचनाओं के साथ काम करने की आवश्यकता होती है।
जावास्क्रिप्ट में, आप उन कक्षाओं या ऑब्जेक्ट्स का उपयोग करके समग्र पैटर्न लागू कर सकते हैं जो एक सामान्य इंटरफ़ेस साझा करते हैं, जो आपको पदानुक्रमित संरचनाएं बनाने में सक्षम बनाता है। आइए व्यावहारिक उदाहरणों के साथ जावास्क्रिप्ट में समग्र पैटर्न को लागू करने और उपयोग करने का तरीका जानें।
मान लीजिए कि आप एक ग्राफ़िक डिज़ाइन एप्लिकेशन बना रहे हैं जिसे सरल आकृतियों और आकृतियों की जटिल रचनाओं (उदाहरण के लिए, समूह) दोनों के साथ काम करने की आवश्यकता है। आप इस पदानुक्रम का प्रतिनिधित्व करने के लिए समग्र पैटर्न का उपयोग कर सकते हैं:
// Component interface class Graphic { draw() {} }
// Leaf class (represents simple shapes) class Circle extends Graphic { constructor() { super(); // Circle-specific properties and methods } draw() { // Draw a circle } }// Composite class (represents groups of shapes) class Group extends Graphic { constructor() { super(); this.graphics = []; } add(graphic) { this.graphics.push(graphic); } draw() { // Draw each graphic in the group this.graphics.forEach((graphic) => graphic.draw()); } }// Usage const circle1 = new Circle(); const circle2 = new Circle(); const group = new Group();group.add(circle1); group.add(circle2);group.draw(); // Draws both circles in the group
इस उदाहरण में, ग्राफ़िक वर्ग घटक इंटरफ़ेस के रूप में कार्य करता है। वृत्त वर्ग सरल आकृतियों का प्रतिनिधित्व करता है, जबकि समूह वर्ग आकृतियों की रचनाओं का प्रतिनिधित्व करता है। सर्कल और ग्रुप दोनों वर्ग ड्रॉ पद्धति को लागू करते हैं, जिससे आप रेंडर करते समय उन्हें समान रूप से व्यवहार कर सकते हैं।
समग्र पैटर्न विभिन्न परिदृश्यों में मूल्यवान है, जिनमें शामिल हैं:
समग्र पैटर्न के साथ काम करते समय, निम्नलिखित पर विचार करें:
ब्रिज पैटर्न एक संरचनात्मक डिज़ाइन पैटर्न है जो किसी वस्तु के अमूर्त को उसके कार्यान्वयन से अलग करता है। यह आपको दोनों के बीच एक पुल बनाने की अनुमति देता है, जिससे वे स्वतंत्र रूप से भिन्न हो सकते हैं। यह पैटर्न विशेष रूप से तब उपयोगी होता है जब आप किसी अमूर्तता और उसके कार्यान्वयन के बीच स्थायी बंधन से बचना चाहते हैं, जिससे आपका कोड अधिक लचीला और रखरखाव योग्य हो जाता है।
जावास्क्रिप्ट में, ब्रिज पैटर्न को कक्षाओं और ऑब्जेक्ट्स का उपयोग करके कार्यान्वित किया जा सकता है जो विभिन्न प्लेटफार्मों या सुविधाओं के लिए अमूर्त और विभिन्न ठोस कार्यान्वयन के लिए एक सार इंटरफ़ेस प्रदान करते हैं। आइए व्यावहारिक उदाहरणों के साथ जावास्क्रिप्ट में ब्रिज पैटर्न को लागू करने और उपयोग करने का तरीका जानें।
मान लीजिए कि आप एक ड्राइंग एप्लिकेशन बना रहे हैं जो वेब ब्राउज़र और मोबाइल डिवाइस जैसे विभिन्न प्लेटफार्मों पर आकृतियाँ प्रस्तुत कर सकता है। आप ड्राइंग आकृतियों (अमूर्त) को रेंडरिंग लॉजिक (कार्यान्वयन) से अलग करने के लिए ब्रिज पैटर्न का उपयोग कर सकते हैं:
// Abstraction class Shape { constructor(renderer) { this.renderer = renderer; }
draw() { // Delegating the drawing to the specific renderer this.renderer.renderShape(this); } }// Implementor interface class Renderer { renderShape(shape) {} }// Concrete Implementors class WebRenderer extends Renderer { renderShape(shape) { console.log(`Drawing on the web: ${shape.constructor.name}`); } }class MobileRenderer extends Renderer { renderShape(shape) { console.log(`Drawing on mobile: ${shape.constructor.name}`); } }// Concrete Abstractions (Shapes) class Circle extends Shape { constructor(renderer) { super(renderer); } }class Square extends Shape { constructor(renderer) { super(renderer); } }// Usage const webRenderer = new WebRenderer(); const mobileRenderer = new MobileRenderer();const circle = new Circle(webRenderer); const square = new Square(mobileRenderer);circle.draw(); // Output: Drawing on the web: Circle square.draw(); // Output: Drawing on mobile: Square
इस उदाहरण में, आकृति वर्ग अमूर्तता (खींची जाने वाली आकृतियाँ) का प्रतिनिधित्व करता है, और रेंडरर वर्ग कार्यान्वयनकर्ता इंटरफ़ेस (प्लेटफ़ॉर्म-विशिष्ट रेंडरिंग लॉजिक) का प्रतिनिधित्व करता है। विभिन्न ठोस कार्यान्वयनकर्ता (वेबरेंडरर और मोबाइलरेंडरर) क्रमशः वेब और मोबाइल प्लेटफ़ॉर्म के लिए रेंडरिंग तर्क प्रदान करते हैं। वृत्त और वर्ग वर्ग आकृतियों का प्रतिनिधित्व करने वाले ठोस अमूर्त हैं।
ब्रिज पैटर्न विभिन्न परिदृश्यों में मूल्यवान है, जिनमें शामिल हैं:
ब्रिज पैटर्न का उपयोग करते समय निम्नलिखित पर विचार करें:
फ्लाईवेट पैटर्न एक संरचनात्मक डिज़ाइन पैटर्न है जिसका उद्देश्य मेमोरी की खपत को कम करना और वस्तुओं के सामान्य भागों को साझा करके प्रदर्शन में सुधार करना है। यह किसी वस्तु की आंतरिक स्थिति (साझा और अपरिवर्तनीय) को उसकी बाहरी स्थिति (अद्वितीय और संदर्भ-निर्भर) से अलग करके इसे प्राप्त करता है। यह पैटर्न विशेष रूप से तब उपयोगी होता है जब आपके पास बड़ी संख्या में समान ऑब्जेक्ट हों और आप मेमोरी फ़ुटप्रिंट को कम करना चाहते हों।
जावास्क्रिप्ट में, आप साझा आंतरिक स्थिति और व्यक्तिगत बाहरी स्थिति का प्रतिनिधित्व करने के लिए कक्षाओं या वस्तुओं का उपयोग करके फ्लाईवेट पैटर्न लागू कर सकते हैं। आइए व्यावहारिक उदाहरणों के साथ जावास्क्रिप्ट में फ्लाईवेट पैटर्न को लागू करने और उपयोग करने का तरीका जानें।
मान लीजिए कि आप एक टेक्स्ट एडिटर विकसित कर रहे हैं जिसमें बड़ी मात्रा में टेक्स्ट प्रदर्शित करने की आवश्यकता है। प्रत्येक कैरेक्टर के लिए एक अलग ऑब्जेक्ट बनाने के बजाय, आप कैरेक्टर ऑब्जेक्ट को साझा करने के लिए फ्लाईवेट पैटर्न का उपयोग कर सकते हैं, जब उनके आंतरिक गुण समान हों (उदाहरण के लिए, फ़ॉन्ट और आकार):
class Character { constructor(char, font, size) { this.char = char; this.font = font; this.size = size; }
render() { console.log(`Rendering character "${this.char}" in ${this.font}, size ${this.size}`); } }class CharacterFactory { constructor() { this.characters = {}; } getCharacter(char, font, size) { const key = `${char}-${font}-${size}`; if (!this.characters[key]) { this.characters[key] = new Character(char, font, size); } return this.characters[key]; } }// Usage const factory = new CharacterFactory();const charA1 = factory.getCharacter('A', 'Arial', 12); const charA2 = factory.getCharacter('A', 'Arial', 12); const charB = factory.getCharacter('B', 'Times New Roman', 14);charA1.render(); // Output: Rendering character "A" in Arial, size 12 charA2.render(); // Output: Rendering character "A" in Arial, size 12 (shared instance) charB.render(); // Output: Rendering character "B" in Times New Roman, size 14
इस उदाहरण में, कैरेक्टर वर्ग चरित्र, फ़ॉन्ट और आकार जैसे आंतरिक गुणों वाले व्यक्तिगत वर्णों का प्रतिनिधित्व करता है। कैरेक्टरफ़ैक्टरी वर्ग यह सुनिश्चित करता है कि समान आंतरिक गुणों वाले वर्णों को डुप्लिकेट करने के बजाय साझा किया जाए।
फ्लाईवेट पैटर्न विभिन्न परिदृश्यों में मूल्यवान है, जिनमें शामिल हैं:
फ्लाईवेट पैटर्न का उपयोग करते समय, निम्नलिखित पर विचार करें:
ऑब्जर्वर पैटर्न एक व्यवहारिक डिज़ाइन पैटर्न है जो वस्तुओं के बीच एक-से-अनेक निर्भरता स्थापित करता है। यह एक वस्तु (विषय या अवलोकन योग्य) को उसकी स्थिति या डेटा में परिवर्तन के बारे में कई पर्यवेक्षकों (श्रोताओं) को सूचित करने की अनुमति देता है। इस पैटर्न का उपयोग आमतौर पर वितरित इवेंट हैंडलिंग सिस्टम को लागू करने के लिए किया जाता है, जहां एक ऑब्जेक्ट की स्थिति अन्य निर्भर ऑब्जेक्ट में ट्रिगर क्रियाओं को बदलती है।
जावास्क्रिप्ट में, आप कस्टम क्लास या इवेंट श्रोता और addEventListener
विधि जैसी अंतर्निहित सुविधाओं का उपयोग करके ऑब्जर्वर पैटर्न को कार्यान्वित कर सकते हैं। आइए जानें कि व्यावहारिक उदाहरणों के साथ जावास्क्रिप्ट में ऑब्जर्वर पैटर्न को कैसे कार्यान्वित और उपयोग किया जाए।
मान लीजिए कि आप एक मौसम एप्लिकेशन बना रहे हैं, और आप चाहते हैं कि मौसम की स्थिति बदलने पर यूआई के विभिन्न हिस्से अपडेट हों। आप ऑब्जर्वर पैटर्न के कस्टम कार्यान्वयन का उपयोग कर सकते हैं:
class WeatherStation { constructor() { this.observers = []; }
addObserver(observer) { this.observers.push(observer); } removeObserver(observer) { const index = this.observers.indexOf(observer); if (index !== -1) { this.observers.splice(index, 1); } } notifyObservers() { this.observers.forEach((observer) => { observer.update(this); }); } setWeatherData(weatherData) { this.weatherData = weatherData; this.notifyObservers(); } }class WeatherDisplay { update(weatherStation) { console.log(`Current weather: ${weatherStation.weatherData}`); } }// Usage const weatherStation = new WeatherStation(); const display1 = new WeatherDisplay(); const display2 = new WeatherDisplay();weatherStation.addObserver(display1); weatherStation.addObserver(display2);weatherStation.setWeatherData('Sunny'); // Both displays update with the new weather data
इस उदाहरण में, वेदरस्टेशन उस विषय के रूप में कार्य करता है जो मौसम डेटा में परिवर्तन होने पर पर्यवेक्षकों (वस्तुओं को प्रदर्शित करता है) को सूचित करता है। पर्यवेक्षक addObserver विधि का उपयोग करके विषय की सदस्यता लेते हैं और परिवर्तनों पर प्रतिक्रिया करने के लिए अद्यतन विधि लागू करते हैं।
जावास्क्रिप्ट इवेंट श्रोताओं का उपयोग करके ऑब्जर्वर पैटर्न को लागू करने के लिए एक अंतर्निहित तरीका भी प्रदान करता है:
class NewsPublisher { constructor() { this.subscribers = []; }
subscribe(subscriber) { this.subscribers.push(subscriber); } unsubscribe(subscriber) { const index = this.subscribers.indexOf(subscriber); if (index !== -1) { this.subscribers.splice(index, 1); } } publishNews(news) { this.subscribers.forEach((subscriber) => { subscriber(news); }); } }// Usage const publisher = new NewsPublisher();const subscriber1 = (news) => { console.log(`Subscriber 1 received news: ${news}`); };const subscriber2 = (news) => { console.log(`Subscriber 2 received news: ${news}`); };publisher.subscribe(subscriber1); publisher.subscribe(subscriber2);publisher.publishNews('Breaking News: Important Announcement');
इस उदाहरण में, समाचार प्रकाशक विषय के रूप में कार्य करता है, और सब्सक्राइबर (फ़ंक्शन) को सब्सक्राइब विधि का उपयोग करके जोड़ा जाता है। पब्लिशन्यूज पद्धति समाचार के साथ अपने कार्यों को लागू करके ग्राहकों को सूचित करती है।
ऑब्जर्वर पैटर्न विभिन्न परिदृश्यों में मूल्यवान है, जिनमें शामिल हैं:
ऑब्जर्वर पैटर्न का उपयोग करते समय, निम्नलिखित पर विचार करें:
रणनीति पैटर्न एक व्यवहारिक डिज़ाइन पैटर्न है जो आपको विनिमेय एल्गोरिदम के एक परिवार को परिभाषित करने, प्रत्येक को समाहित करने और उन्हें विनिमेय बनाने की अनुमति देता है। यह ग्राहकों को रनटाइम पर गतिशील रूप से उचित एल्गोरिदम चुनने में सक्षम बनाता है। यह पैटर्न एल्गोरिदम के व्यवहार को इसका उपयोग करने वाले संदर्भ से अलग करके लचीलेपन और पुन: प्रयोज्य को बढ़ावा देता है।
जावास्क्रिप्ट में, आप विभिन्न रणनीतियों और एक संदर्भ ऑब्जेक्ट का प्रतिनिधित्व करने के लिए ऑब्जेक्ट या फ़ंक्शंस का उपयोग करके रणनीति पैटर्न लागू कर सकते हैं जो इन रणनीतियों के बीच स्विच कर सकता है। आइए व्यावहारिक उदाहरणों के साथ जावास्क्रिप्ट में रणनीति पैटर्न को लागू करने और उपयोग करने का तरीका जानें।
मान लीजिए कि आप एक ई-कॉमर्स एप्लिकेशन विकसित कर रहे हैं, और आप विभिन्न प्रकार के ग्राहकों के लिए छूट की गणना करना चाहते हैं। आप छूट रणनीतियों को समाहित करने के लिए रणनीति पैटर्न का उपयोग कर सकते हैं:
// Discount Strategies const regularCustomerDiscount = (amount) => amount * 0.1; // 10% discount const premiumCustomerDiscount = (amount) => amount * 0.2; // 20% discount
// Context class ShoppingCart { constructor(discountStrategy) { this.items = []; this.discountStrategy = discountStrategy; } addItem(item) { this.items.push(item); } calculateTotal() { const subtotal = this.items.reduce((total, item) => total + item.price, 0); return subtotal - this.discountStrategy(subtotal); } }// Usage const regularCustomerCart = new ShoppingCart(regularCustomerDiscount); const premiumCustomerCart = new ShoppingCart(premiumCustomerDiscount);regularCustomerCart.addItem({ name: 'Item 1', price: 50 }); premiumCustomerCart.addItem({ name: 'Item 2', price: 100 });console.log(`Regular Customer Total: $${regularCustomerCart.calculateTotal()}`); // Output: $45 (after 10% discount) console.log(`Premium Customer Total: $${premiumCustomerCart.calculateTotal()}`); // Output: $80 (after 20% discount)
इस उदाहरण में, हम दो छूट रणनीतियों को फ़ंक्शन (नियमित ग्राहक छूट और प्रीमियम ग्राहक छूट) के रूप में परिभाषित करते हैं। शॉपिंगकार्ट वर्ग एक छूट रणनीति को एक पैरामीटर के रूप में लेता है और चुनी गई रणनीति के आधार पर कुल कीमत की गणना करता है।
रणनीति पैटर्न विभिन्न परिदृश्यों में मूल्यवान है, जिनमें शामिल हैं:
रणनीति पैटर्न का उपयोग करते समय, निम्नलिखित पर विचार करें:
कमांड पैटर्न एक व्यवहारिक डिज़ाइन पैटर्न है जो किसी अनुरोध या सरल ऑपरेशन को एक स्टैंडअलोन ऑब्जेक्ट में बदल देता है। यह आपको विभिन्न अनुरोधों के साथ ऑब्जेक्ट को पैरामीटराइज़ करने, अनुरोध के निष्पादन में देरी या कतार लगाने और पूर्ववत संचालन का समर्थन करने की अनुमति देता है। यह पैटर्न अनुरोध भेजने वाले को उसके रिसीवर से अलग कर देता है, जिससे कोड को बढ़ाना और बनाए रखना आसान हो जाता है।
जावास्क्रिप्ट में, आप उन कमांडों को निष्पादित करने वाले कमांड और इनवॉकर्स का प्रतिनिधित्व करने के लिए ऑब्जेक्ट्स या क्लासेस का उपयोग करके कमांड पैटर्न लागू कर सकते हैं। आइए व्यावहारिक उदाहरणों के साथ जावास्क्रिप्ट में कमांड पैटर्न को लागू करने और उपयोग करने का तरीका जानें।
मान लीजिए कि आप एक स्मार्ट होम के लिए रिमोट कंट्रोल एप्लिकेशन विकसित कर रहे हैं, और आप विभिन्न उपकरणों को नियंत्रित करने के लिए एक लचीला तरीका बनाना चाहते हैं।
आप कमांड पैटर्न का उपयोग कर सकते हैं:
// Command interface class Command { execute() {} }
// Concrete Commands class LightOnCommand extends Command { constructor(light) { super(); this.light = light; } execute() { this.light.turnOn(); } }class LightOffCommand extends Command { constructor(light) { super(); this.light = light; } execute() { this.light.turnOff(); } }// Receiver (Device) class Light { turnOn() { console.log('Light is on.'); } turnOff() { console.log('Light is off.'); } }// Invoker (Remote Control) class RemoteControl { constructor() { this.commands = []; } addCommand(command) { this.commands.push(command); } executeCommands() { this.commands.forEach((command) => { command.execute(); }); } }// Usage const livingRoomLight = new Light(); const kitchenLight = new Light();const livingRoomLightOn = new LightOnCommand(livingRoomLight); const livingRoomLightOff = new LightOffCommand(livingRoomLight); const kitchenLightOn = new LightOnCommand(kitchenLight); const kitchenLightOff = new LightOffCommand(kitchenLight);const remoteControl = new RemoteControl();remoteControl.addCommand(livingRoomLightOn); remoteControl.addCommand(kitchenLightOff);remoteControl.executeCommands(); // Output: "Light is on." (for living room) // Output: "Light is off." (for kitchen)
इस उदाहरण में, कमांड पैटर्न का उपयोग लाइटों को चालू और बंद करने की क्रियाओं को समाहित करने के लिए किया जाता है। रिमोटकंट्रोल इनवॉकर के रूप में कार्य करता है, और ठोस कमांड (उदाहरण के लिए, लाइटऑनकमांड और लाइटऑफकमांड) निष्पादित होने वाली क्रियाओं को समाहित करता है।
कमांड पैटर्न विभिन्न परिदृश्यों में मूल्यवान है, जिनमें शामिल हैं:
कमांड पैटर्न का उपयोग करते समय, निम्नलिखित पर विचार करें:
राज्य पैटर्न एक व्यवहारिक डिज़ाइन पैटर्न है जो किसी वस्तु की आंतरिक स्थिति बदलने पर उसके व्यवहार को बदलने की अनुमति देता है। यह राज्यों को अलग-अलग वर्गों के रूप में समाहित करता है और व्यवहार को वर्तमान राज्य ऑब्जेक्ट में सौंपता है। यह पैटर्न जटिल राज्य परिवर्तनों को प्रबंधित करने में मदद करता है और "खुले-बंद" सिद्धांत को बढ़ावा देता है, जिससे मौजूदा कोड को संशोधित किए बिना नए राज्यों को जोड़ना आसान हो जाता है।
जावास्क्रिप्ट में, आप राज्यों का प्रतिनिधित्व करने के लिए कक्षाओं और एक संदर्भ वस्तु का उपयोग करके राज्य पैटर्न को कार्यान्वित कर सकते हैं जो वर्तमान स्थिति में अपने व्यवहार को दर्शाता है। आइए जानें कि व्यावहारिक उदाहरणों के साथ जावास्क्रिप्ट में स्टेट पैटर्न को कैसे लागू किया जाए और उसका उपयोग कैसे किया जाए।
मान लीजिए आप एक वेंडिंग मशीन विकसित कर रहे हैं जो विभिन्न उत्पाद वितरित करती है। वेंडिंग मशीन का व्यवहार उसकी वर्तमान स्थिति पर निर्भर करता है, जैसे "तैयार," "वितरण," या "बिक गया"। आप इस व्यवहार को मॉडल करने के लिए राज्य पैटर्न का उपयोग कर सकते हैं:
// State interface class VendingMachineState { insertMoney() {} ejectMoney() {} selectProduct() {} dispenseProduct() {} }
// Concrete States class ReadyState extends VendingMachineState { constructor(machine) { super(); this.machine = machine; } insertMoney() { console.log('Money inserted.'); this.machine.setState(this.machine.getDispensingState()); } selectProduct() { console.log('Please insert money first.'); } }class DispensingState extends VendingMachineState { constructor(machine) { super(); this.machine = machine; } dispenseProduct() { console.log('Product dispensed.'); this.machine.setState(this.machine.getReadyState()); } }class VendingMachine { constructor() { this.readyState = new ReadyState(this); this.dispensingState = new DispensingState(this); this.currentState = this.readyState; } setState(state) { this.currentState = state; } getReadyState() { return this.readyState; } getDispensingState() { return this.dispensingState; } insertMoney() { this.currentState.insertMoney(); } selectProduct() { this.currentState.selectProduct(); } dispenseProduct() { this.currentState.dispenseProduct(); } }// Usage const vendingMachine = new VendingMachine();vendingMachine.selectProduct(); // Output: "Please insert money first." vendingMachine.insertMoney(); // Output: "Money inserted." vendingMachine.dispenseProduct(); // Output: "Product dispensed."
इस उदाहरण में, राज्य पैटर्न का उपयोग वेंडिंग मशीन के व्यवहार को प्रबंधित करने के लिए किया जाता है। "रेडी" और "डिस्पेंसिंग" जैसे राज्यों को अलग-अलग वर्गों के रूप में दर्शाया जाता है, और संदर्भ (वेंडिंग मशीन) अपने व्यवहार को वर्तमान स्थिति में दर्शाता है।
राज्य पैटर्न विभिन्न परिदृश्यों में मूल्यवान है, जिनमें शामिल हैं:
राज्य पैटर्न का उपयोग करते समय, निम्नलिखित पर विचार करें:
जिम्मेदारी पैटर्न की श्रृंखला एक व्यवहारिक डिज़ाइन पैटर्न है जो अनुरोध को संभालने के लिए वस्तुओं की एक श्रृंखला बनाने में आपकी सहायता करता है। श्रृंखला में प्रत्येक वस्तु के पास अनुरोध को संसाधित करने या उसे श्रृंखला में अगली वस्तु तक भेजने का अवसर होता है। यह अनुरोध भेजने वाले को उसके प्राप्तकर्ताओं से अलग कर देता है और कई हैंडलरों को श्रृंखला में रहने की अनुमति देता है। यह पैटर्न आपको क्लाइंट कोड को प्रभावित किए बिना हैंडलर जोड़ने या संशोधित करने में सक्षम करके लचीलेपन और विस्तारशीलता को बढ़ावा देता है।
जावास्क्रिप्ट में, आप उन वस्तुओं या वर्गों का उपयोग करके जिम्मेदारी पैटर्न की श्रृंखला को कार्यान्वित कर सकते हैं जो हैंडलर और अनुरोध शुरू करने वाले क्लाइंट का प्रतिनिधित्व करते हैं। प्रत्येक हैंडलर के पास श्रृंखला में अगले हैंडलर का संदर्भ होता है। आइए जानें कि व्यावहारिक उदाहरणों के साथ जावास्क्रिप्ट में जिम्मेदारी पैटर्न की श्रृंखला को कैसे कार्यान्वित और उपयोग किया जाए।
मान लीजिए कि आप एक ऑर्डर प्रोसेसिंग सिस्टम विकसित कर रहे हैं, और आप उनकी कुल राशि के आधार पर ऑर्डर को संभालना चाहते हैं। आप हैंडलर्स की एक श्रृंखला बनाने के लिए जिम्मेदारी पैटर्न की श्रृंखला का उपयोग कर सकते हैं, जिनमें से प्रत्येक एक निश्चित मूल्य सीमा के भीतर ऑर्डर संसाधित करने के लिए जिम्मेदार है:
// Handler interface class OrderHandler { constructor() { this.nextHandler = null; }
setNextHandler(handler) { this.nextHandler = handler; } handleOrder(order) { if (this.canHandleOrder(order)) { this.processOrder(order); } else if (this.nextHandler) { this.nextHandler.handleOrder(order); } else { console.log('No handler can process this order.'); } } canHandleOrder(order) {} processOrder(order) {} }// Concrete Handlers class SmallOrderHandler extends OrderHandler { canHandleOrder(order) { return order.amount <= 100; } processOrder(order) { console.log(`Processing small order for ${order.amount}`); } }class MediumOrderHandler extends OrderHandler { canHandleOrder(order) { return order.amount <= 500; } processOrder(order) { console.log(`Processing medium order for ${order.amount}`); } }class LargeOrderHandler extends OrderHandler { canHandleOrder(order) { return order.amount > 500; } processOrder(order) { console.log(`Processing large order for ${order.amount}`); } }// Client class Order { constructor(amount) { this.amount = amount; } }// Usage const smallOrderHandler = new SmallOrderHandler(); const mediumOrderHandler = new MediumOrderHandler(); const largeOrderHandler = new LargeOrderHandler();smallOrderHandler.setNextHandler(mediumOrderHandler); mediumOrderHandler.setNextHandler(largeOrderHandler);const order1 = new Order(80); const order2 = new Order(250); const order3 = new Order(600);smallOrderHandler.handleOrder(order1); // Output: "Processing small order for 80" smallOrderHandler.handleOrder(order2); // Output: "Processing medium order for 250" smallOrderHandler.handleOrder(order3); // Output: "Processing large order for 600"
इस उदाहरण में, जिम्मेदारी पैटर्न की श्रृंखला का उपयोग विभिन्न मात्रा के आदेशों को संभालने के लिए किया जाता है। स्मॉलऑर्डरहैंडलर, मीडियमऑर्डरहैंडलर और लार्जऑर्डरहैंडलर जैसे हैंडलर प्रत्येक यह निर्धारित करते हैं कि वे ऑर्डर की राशि के आधार पर ऑर्डर को संसाधित कर सकते हैं या नहीं। यदि वे कर सकते हैं, तो वे इसे संसाधित करते हैं; अन्यथा, वे श्रृंखला में अगले हैंडलर को ऑर्डर भेज देते हैं।
जिम्मेदारी पैटर्न की श्रृंखला विभिन्न परिदृश्यों में मूल्यवान है, जिनमें शामिल हैं:
जिम्मेदारी पैटर्न की श्रृंखला का उपयोग करते समय, निम्नलिखित पर विचार करें:
विज़िटर पैटर्न एक व्यवहारिक डिज़ाइन पैटर्न है जो आपको एल्गोरिदम को उस ऑब्जेक्ट संरचना से अलग करने की अनुमति देता है जिस पर यह संचालित होता है। यह अपनी कक्षाओं को संशोधित किए बिना ऑब्जेक्ट में नए ऑपरेशन जोड़ने का एक तरीका प्रदान करता है, जिससे जटिल ऑब्जेक्ट पदानुक्रम के लिए कार्यक्षमता का विस्तार करना आसान हो जाता है। यह पैटर्न विशेष रूप से तब उपयोगी होता है जब आपके पास अलग-अलग तत्वों का एक सेट होता है और आप उनके कोड को संशोधित किए बिना उन पर विभिन्न ऑपरेशन करना चाहते हैं।
जावास्क्रिप्ट में, आप ऑब्जेक्ट संरचना के भीतर तत्वों पर जाने वाले विज़िटर का प्रतिनिधित्व करने के लिए फ़ंक्शंस या कक्षाओं का उपयोग करके विज़िटर पैटर्न लागू कर सकते हैं। आइए व्यावहारिक उदाहरणों के साथ जावास्क्रिप्ट में विज़िटर पैटर्न को लागू करने और उपयोग करने का तरीका जानें।
मान लीजिए कि आप एक सामग्री प्रबंधन प्रणाली विकसित कर रहे हैं जहां आपके पास लेख, चित्र और वीडियो जैसे विभिन्न प्रकार के सामग्री तत्व हैं। आप इन तत्वों पर उनकी कक्षाओं को संशोधित किए बिना विभिन्न ऑपरेशन करना चाहते हैं, जैसे कि रेंडरिंग और निर्यात करना। आप विज़िटर पैटर्न का उपयोग कर सकते हैं:
// Element interface class ContentElement { accept(visitor) {} }
// Concrete Elements class Article extends ContentElement { accept(visitor) { visitor.visitArticle(this); } }class Image extends ContentElement { accept(visitor) { visitor.visitImage(this); } }class Video extends ContentElement { accept(visitor) { visitor.visitVideo(this); } }// Visitor interface class Visitor { visitArticle(article) {} visitImage(image) {} visitVideo(video) {} }// Concrete Visitors class RendererVisitor extends Visitor { visitArticle(article) { console.log(`Rendering article: ${article.title}`); } visitImage(image) { console.log(`Rendering image: ${image.caption}`); } visitVideo(video) { console.log(`Rendering video: ${video.title}`); } }class ExportVisitor extends Visitor { visitArticle(article) { console.log(`Exporting article: ${article.title}`); } visitImage(image) { console.log(`Exporting image: ${image.caption}`); } visitVideo(video) { console.log(`Exporting video: ${video.title}`); } }// Usage const elements = [new Article('Article 1'), new Image('Image 1'), new Video('Video 1')]; const renderer = new RendererVisitor(); const exporter = new ExportVisitor();elements.forEach((element) => { element.accept(renderer); element.accept(exporter); });
इस उदाहरण में, हमारे पास आलेख, छवि और वीडियो जैसे सामग्री तत्व हैं, और हम उनकी कक्षाओं को संशोधित किए बिना उन पर प्रतिपादन और निर्यात संचालन करना चाहते हैं। हम इसे रेंडररविज़िटर और एक्सपोर्टविज़िटर जैसी विज़िटर कक्षाओं को लागू करके प्राप्त करते हैं जो तत्वों पर जाते हैं और वांछित संचालन करते हैं।
विज़िटर पैटर्न विभिन्न परिदृश्यों में मूल्यवान है, जिनमें शामिल हैं:
विज़िटर पैटर्न का उपयोग करते समय, निम्नलिखित पर विचार करें:
जावास्क्रिप्ट में डिज़ाइन पैटर्न की इस व्यापक खोज में, हमने विभिन्न पैटर्न का पता लगाया है जो डेवलपर्स को लचीला, रखरखाव योग्य और कुशल कोड बनाने के लिए सशक्त बनाता है। प्रत्येक डिज़ाइन पैटर्न विशिष्ट समस्याओं का समाधान करता है और सामान्य सॉफ़्टवेयर डिज़ाइन चुनौतियों के लिए सुरुचिपूर्ण समाधान प्रदान करता है।
हमने डिज़ाइन पैटर्न की मूलभूत अवधारणा को समझकर शुरुआत की और उन्हें तीन प्रमुख समूहों में वर्गीकृत किया: रचनात्मक, संरचनात्मक और व्यवहारिक पैटर्न। प्रत्येक श्रेणी में, हमने लोकप्रिय डिज़ाइन पैटर्न की जांच की और जावास्क्रिप्ट में उनके व्यावहारिक कार्यान्वयन का प्रदर्शन किया।
हमारे द्वारा कवर किए गए प्रमुख डिज़ाइन पैटर्न का संक्षिप्त विवरण यहां दिया गया है:
रचनात्मक पैटर्न: ये पैटर्न ऑब्जेक्ट निर्माण तंत्र पर ध्यान केंद्रित करते हैं, जिसमें क्लास के एकल उदाहरण को सुनिश्चित करने के लिए सिंगलटन पैटर्न, लचीली फैक्टरियों के साथ ऑब्जेक्ट बनाने के लिए फैक्ट्री और एब्सट्रैक्ट फैक्ट्री पैटर्न, चरण दर चरण जटिल वस्तुओं के निर्माण के लिए बिल्डर पैटर्न, क्लोनिंग के लिए प्रोटोटाइप पैटर्न शामिल हैं। ऑब्जेक्ट के कुशल पुन: उपयोग के लिए ऑब्जेक्ट और ऑब्जेक्ट पूल पैटर्न।
संरचनात्मक पैटर्न: ये पैटर्न वस्तु संरचना से निपटते हैं, सरल घटकों से जटिल संरचनाएं बनाने के तरीके प्रदान करते हैं। हमने इंटरफेस को अनुकूलित करने के लिए एडाप्टर पैटर्न, वस्तुओं में व्यवहार को गतिशील रूप से जोड़ने के लिए डेकोरेटर पैटर्न, वस्तुओं तक पहुंच को नियंत्रित करने के लिए प्रॉक्सी पैटर्न, पेड़ संरचनाओं में वस्तुओं की रचना करने के लिए समग्र पैटर्न, कार्यान्वयन से अमूर्त को अलग करने के लिए ब्रिज पैटर्न और फ्लाईवेट की खोज की। सामान्य स्थिति साझा करके मेमोरी उपयोग को कम करने का पैटर्न।
व्यवहार पैटर्न: ये पैटर्न वस्तुओं के बीच बातचीत और संचार से संबंधित हैं। हमने वितरित इवेंट हैंडलिंग सिस्टम को लागू करने के लिए ऑब्जर्वर पैटर्न, विनिमेय एल्गोरिदम को एनकैप्सुलेट करने के लिए रणनीति पैटर्न, स्टैंडअलोन ऑब्जेक्ट्स में अनुरोधों को बदलने के लिए कमांड पैटर्न, आंतरिक स्थिति के आधार पर ऑब्जेक्ट व्यवहार के प्रबंधन के लिए राज्य पैटर्न, जिम्मेदारी पैटर्न की श्रृंखला के निर्माण के लिए कवर किया। प्रसंस्करण अनुरोधों के लिए हैंडलर की श्रृंखला, और ऑब्जेक्ट संरचनाओं से एल्गोरिदम को अलग करने के लिए विज़िटर पैटर्न।
डिज़ाइन पैटर्न एक डेवलपर के टूलकिट में मूल्यवान उपकरण हैं, जो स्केलेबल और रखरखाव योग्य कोडबेस के निर्माण को सक्षम करते हैं। अपने जावास्क्रिप्ट प्रोजेक्ट्स में इन पैटर्न को समझने और लागू करने से आप अधिक कुशल, अनुकूलनीय और मजबूत सॉफ्टवेयर लिख सकते हैं।
याद रखें कि डिज़ाइन पैटर्न एक आकार-फिट-सभी समाधान नहीं हैं, और उनकी प्रयोज्यता आपके प्रोजेक्ट की विशिष्ट आवश्यकताओं और चुनौतियों पर निर्भर करती है। सर्वोत्तम परिणाम प्राप्त करने के लिए उन्हें कब और कैसे लागू करना है, इस पर सावधानीपूर्वक विचार करें।
जैसे-जैसे आप एक जावास्क्रिप्ट डेवलपर के रूप में आगे बढ़ते रहेंगे, इन डिज़ाइन पैटर्न में महारत हासिल करने से आप आत्मविश्वास और रचनात्मकता के साथ जटिल सॉफ़्टवेयर डिज़ाइन चुनौतियों से निपटने में सशक्त होंगे। चाहे आप वेब एप्लिकेशन, गेम इंजन, या कोई अन्य सॉफ़्टवेयर बना रहे हों, डिज़ाइन पैटर्न सुरुचिपूर्ण और रखरखाव योग्य कोड तैयार करने में आपके सहयोगी होंगे। हैप्पी कोडिंग!
यहाँ भी प्रकाशित किया गया है.