जावास्क्रिप्ट में रणनीति पैटर्न

अनुवादक से:
मैं मेरे लिए एक नए रणनीति पैटर्न का अध्ययन करने जा रहा था, लेकिन मुझे जावास्क्रिप्ट में इसके कार्यान्वयन का एक समझदार रूसी विवरण नहीं मिला। एक विकी लेख इसकी जटिलता में डराने वाला है, और उदाहरण की स्पष्टता खराब है। इसलिए मैंने इस लेख का अनुवाद किया, उसी समय यह समझ लिया कि यह पैटर्न क्या है।
Spoilers और ग्रे पाठ मेरी टिप्पणी है।
अगला, हम उदाहरणों को देखेंगे कि कैसे मैं जावास्क्रिप्ट में स्ट्रैटेजी का उपयोग करता हूं, और यह कैसे एक वास्तविक पुस्तकालय द्वारा उपयोग किया जाता है, इसे छोटे भागों में तोड़ने के लिए।

मुझे स्ट्रेटेजी पैटर्न पसंद है। मैं जहां भी संभव हो, इसका उपयोग करने की कोशिश करता हूं। अनिवार्य रूप से, यह डेलिगेशन का उपयोग उन वर्गों से अलग एल्गोरिदम करने के लिए करता है जो उनका उपयोग करते हैं।

इस दृष्टिकोण के कई फायदे हैं।
सबसे पहले, यह उपयोग करने के लिए एल्गोरिथ्म के किस संस्करण को चुनने के लिए जटिल सशर्त निर्माण से बचा जाता है।
दूसरे, यह कनेक्टिविटी को कमजोर करता है , जिससे ग्राहक जटिलता कम हो जाती है, और वर्ग एकत्रीकरण के पक्ष में उपवर्गों की अस्वीकृति को प्रोत्साहित करता है।
तीसरा, यह प्रतिरूपकता और परीक्षणशीलता में सुधार करता है।

स्ट्रैटेजी के कार्यान्वयन में, आमतौर पर दो प्रतिभागियों का उपयोग किया जाता है:
बाद में:
पैटर्न - ही पैटर्न।
रणनीति एल्गोरिथ्म का एक अलग कार्यान्वयन है।

अगला, हम उदाहरणों को देखेंगे कि कैसे मैं जावास्क्रिप्ट में स्ट्रैटेजी का उपयोग करता हूं, और यह कैसे एक वास्तविक पुस्तकालय द्वारा उपयोग किया जाता है, इसे छोटे भागों में तोड़ने के लिए।

एक समारोह के रूप में रणनीति

बिल्ट-इन फ़नक्शन क्लास एक एल्गोरिथ्म को एनकैप्सुलेट करने का एक शानदार तरीका प्रदान करता है। और इसका मतलब है कि कार्यों को रणनीतियों के रूप में इस्तेमाल किया जा सकता है। बस क्लाइंट को फंक्शन पास करें और सुनिश्चित करें कि क्लाइंट इसका उपयोग करता है।

हम इसका उदाहरण देते हैं। मान लीजिए हम एक अभिवादक वर्ग बनाना चाहते हैं। उनका काम लोगों का अभिवादन करना है। और हम यह भी चाहते हैं कि ग्रीटर अलग-अलग तरीकों से उनका अभिवादन कर सकें। यही है, हमें एल्गोरिथ्म के कई अलग-अलग कार्यान्वयन की आवश्यकता है । ऐसा करने के लिए, हम विभिन्न ग्रीटिंग रणनीतियाँ बनाएंगे। इसके बाद, एक एल्गोरिथ्म एक अभिवादन है।
// Greeter -  ,    . //         var Greeter = function(strategy) { this.strategy = strategy; }; // Greeter   greet, //       //  ,    Greeter.prototype.greet = function() { return this.strategy(); }; //     , //       //  : var politeGreetingStrategy = function() { console.log("Hello."); }; var friendlyGreetingStrategy = function() { console.log("Hey!"); }; var boredGreetingStrategy = function() { console.log("sup."); }; //   ! var politeGreeter = new Greeter(politeGreetingStrategy); var friendlyGreeter = new Greeter(friendlyGreetingStrategy); var boredGreeter = new Greeter(boredGreetingStrategy); console.log(politeGreeter.greet()); //=> Hello. console.log(friendlyGreeter.greet()); //=> Hey! console.log(boredGreeter.greet()); //=> sup. 
इस कोड में एक त्रुटि है (धन्यवाद बश्टनिक )। चूंकि कंसोल का आउटपुट रणनीति एल्गोरिदम में पहले से ही निर्धारित है, और ग्रीटिंग विधि एक फ़ंक्शन देता है जो कुछ भी वापस नहीं करता है, अंतिम तीन पंक्तियों को प्रतिस्थापित किया जाना चाहिए
इन
 politeGreeter.greet(); //=> Hello. friendlyGreeter.greet(); //=> Hey! boredGreeter.greet(); //=> sup. 

उपरोक्त उदाहरण में, हमने एक ग्रीट क्लाइंट और तीन अलग-अलग रणनीतियों का निर्माण किया । जाहिर है, ग्रीट एल्गोरिथ्म का उपयोग करना जानता है , लेकिन इसके हुड के नीचे क्या है, इसका कोई पता नहीं है।

लेकिन जटिल एल्गोरिदम के लिए, फ़ंक्शन अक्सर पर्याप्त नहीं होते हैं। इस मामले में, OOP शैली स्ट्रैटेजी का उपयोग करना बेहतर है।

एक वर्ग के रूप में रणनीति

कक्षाएं भी रणनीति हो सकती हैं , खासकर उन मामलों में जहां एल्गोरिदम उपरोक्त उदाहरण में आविष्कार किए गए लोगों की तुलना में अधिक जटिल हैं। कक्षाओं का उपयोग करना आपको प्रत्येक रणनीति के लिए एक इंटरफ़ेस को परिभाषित करने की अनुमति देता है।

इसे एक उदाहरण के रूप में देखें।
यह निहित है कि यह कोड उदाहरण से पहले है।
 var Greeter = function(strategy) { this.strategy = strategy; }; 
 //       Javascript //   ,      //     , //          . //    ,      var Strategy = function() {}; Strategy.prototype.execute = function() { throw new Error('Strategy#execute needs to be overridden.') }; //           //        `Strategy`. //  ,    , //      `execute` var GreetingStrategy = function() {}; GreetingStrategy.prototype = Object.create(Strategy.prototype); //   `execute`,       //    `Strategy`   . //  ,       . //      (Template Method). //      . GreetingStrategy.prototype.execute = function() { return this.sayHi() + this.sayBye(); }; GreetingStrategy.prototype.sayHi = function() { return "Hello, "; }; GreetingStrategy.prototype.sayBye = function() { return "Goodbye."; }; //      . //    -   `Greeter`. Greeter.prototype.greet = function() { return this.strategy.execute(); }; var greeter = new Greeter(new GreetingStrategy()); greeter.greet() //=> 'Hello, Goodbye.' 
हमने निष्पादन विधि के साथ रणनीति को एक वस्तु (या वर्ग) के रूप में परिभाषित किया। ग्राहक इस वर्ग से संबंधित किसी भी रणनीति का उपयोग कर सकता है।

GreetingStrategy देखें । सबसे दिलचस्प निष्पादन विधि के ओवरराइड में है। यह इस वर्ग के अन्य तरीकों पर निर्भर करता है। अब, इस श्रेणी को प्राप्त करने वाले ऑब्जेक्ट मुख्य एल्गोरिथ्म को बदलने के बिना व्यक्तिगत तरीकों को बदल सकते हैं, जैसे कि SayHi या sayBye । इस पैटर्न को टेम्प्लेट विधि कहा जाता है और यह STRATEGY के साथ पूरी तरह से जोड़ती है।

आइए देखें कैसे।
 //   GreetingStrategy#execute    . //    ,     , //       ( `execute`) var PoliteGreetingStrategy = function() {}; PoliteGreetingStrategy.prototype = Object.create(GreetingStrategy.prototype); PoliteGreetingStrategy.prototype.sayHi = function() { return "Welcome sir, "; }; var FriendlyGreetingStrategy = function() {}; FriendlyGreetingStrategy.prototype = Object.create(GreetingStrategy.prototype); FriendlyGreetingStrategy.prototype.sayHi = function() { return "Hey, "; }; var BoredGreetingStrategy = function() {}; BoredGreetingStrategy.prototype = Object.create(GreetingStrategy.prototype); BoredGreetingStrategy.prototype.sayHi = function() { return "sup, "; }; var politeGreeter = new Greeter(new PoliteGreetingStrategy()); var friendlyGreeter = new Greeter(new FriendlyGreetingStrategy()); var boredGreeter = new Greeter(new BoredGreetingStrategy()); politeGreeter.greet(); //=> 'Welcome sir, Goodbye.' friendlyGreeter.greet(); //=> 'Hey, Goodbye.' boredGreeter.greet(); //=> 'sup, Goodbye.' 
निष्पादित विधि को परिभाषित करके, GreetingStrategy एल्गोरिदम का एक परिवार बनाता है। उपरोक्त स्निपेट में, हमने उनकी कई किस्में बनाकर इसका लाभ उठाया।

उपवर्गों का उपयोग किए बिना भी, ग्रीटिंग के पास अभी भी बहुरूपता है । हमें जिस एल्गोरिथ्म की आवश्यकता है उसे आह्वान करने के लिए किसी अन्य प्रकार के ग्रीटिंग पर स्विच करने की आवश्यकता नहीं है। अब वे सभी हर नए ग्रीटिंग में हैं
 var greeters = [ new Greeter(new BoredGreetingStrategy()), new Greeter(new PoliteGreetingStrategy()), new Greeter(new FriendlyGreetingStrategy()), ]; greeters.forEach(function(greeter) { //    `greeter`     //      . //      `greet`, //        . greeter.greet(); }); 


वास्तविक कोड में संरचना

STRATEGIES का उपयोग करने के मेरे पसंदीदा उदाहरणों में से एक Passport.js लाइब्रेरी है।

Passport.js नोड में एक आसान तरीका प्रदान करता है। यह बड़ी संख्या में प्रदाताओं (फेसबुक, ट्विटर, गूगल आदि) का समर्थन करता है, जिनमें से प्रत्येक को एक अलग रणनीति के रूप में प्रस्तुत किया जाता है।

पुस्तकालय एक npm पैकेज के साथ-साथ इसकी सभी रणनीतियों के रूप में उपलब्ध है। प्रोग्रामर यह तय करने के लिए स्वतंत्र है कि इस विशेष मामले में कौन सा एनपीएम पैकेज स्थापित करना है। यहाँ कोड का एक टुकड़ा है जो दिखाता है कि यह कैसे काम करता है:
 //    http://passportjs.org var passport = require('passport') //      npm-. //     . , LocalStrategy = require('passport-local').Strategy , FacebookStrategy = require('passport-facebook').Strategy; // Passport      . passport.use(new LocalStrategy( function(username, password, done) { User.findOne({ username: username }, function (err, user) { if (err) { return done(err); } if (!user) { return done(null, false, { message: 'Incorrect username.' }); } if (!user.validPassword(password)) { return done(null, false, { message: 'Incorrect password.' }); } return done(null, user); }); } )); // ,    Facebook passport.use(new FacebookStrategy({ clientID: FACEBOOK_APP_ID, clientSecret: FACEBOOK_APP_SECRET, callbackURL: "http://www.example.com/auth/facebook/callback" }, function(accessToken, refreshToken, profile, done) { User.findOrCreate(..., function(err, user) { if (err) { return done(err); } done(null, user); }); } )); 
Passport.js लाइब्रेरी में केवल सरल प्रमाणीकरण तंत्र के एक जोड़े हैं। इसमें उनके और प्रसंग के अलावा कुछ भी नहीं है। यह आर्किटेक्चर तीसरे पक्ष के प्रोग्रामर को प्रोजेक्ट को अव्यवस्थित किए बिना आसानी से अपने स्वयं के प्रमाणीकरण तंत्र को लागू करने की अनुमति देता है।

नैतिकता

रणनीति पैटर्न आपके कोड के प्रतिरूपकता और परिवर्तनशीलता को बढ़ाने का एक तरीका प्रदान करता है। लेकिन इसका मतलब यह नहीं है कि इसका उपयोग हर जगह के साथ या बिना किया जाना चाहिए। रनटाइम पर ऑब्जेक्ट में कार्यक्षमता जोड़ने के लिए अशुद्धियों का उपयोग करना भी उपयोगी है। और कभी-कभी अच्छी पुरानी बतख टाइपिंग की शैली में एक साधारण बहुरूपता पर्याप्त है।

एक तरीका या दूसरा, पहले स्थान पर स्ट्रैटेजी का उपयोग करके, आप आर्किटेक्चर के बड़े ओवरहेड से बचते हुए, कोड को स्केल करने की अनुमति देता है। यह Passport.js में देखा जा सकता है, जिसमें इस पैटर्न का उपयोग अन्य प्रोग्रामर से नई रणनीतियों के दर्द रहित जोड़ में योगदान देता है।

Source: https://habr.com/ru/post/In191480/


All Articles