रणनीति (कार्लो चुंग द्वारा "आईओएस के लिए प्रो ऑब्जेक्टिव-सी डिज़ाइन पैटर्न" पुस्तक से अंग्रेजी अध्याय "रणनीति" का अनुवाद)

क्या आपको याद है कि पिछली बार आपने कई अलग-अलग एल्गोरिदम के साथ कोड का एक ब्लॉक शुरू किया था और अगर-जो उपयोग करने के लिए निर्धारित किया गया था, तो अन्य / स्विच-केस स्थितियों से स्पेगेटी का उपयोग किया था। एल्गोरिदम समान वर्गों के कार्यों / विधियों का एक सेट हो सकता है जो समान समस्याओं को हल करते हैं। उदाहरण के लिए, आपके पास इनपुट जांचने की एक प्रक्रिया है। डेटा स्वयं किसी भी प्रकार का हो सकता है (उदाहरण के लिए, CGFloat



, NSString



, NSInteger



, आदि)। डेटा प्रकारों में से प्रत्येक को अलग-अलग सत्यापन एल्गोरिदम की आवश्यकता होती है। यदि आप प्रत्येक एल्गोरिथ्म को एक ऑब्जेक्ट के रूप में एन्क्रिप्ट कर सकते हैं, तो आप डेटा की जांच करने और यह निर्धारित करने के लिए कि क्या एल्गोरिथम की आवश्यकता है, अगर-और / स्विच-केस स्टेटमेंट के समूह का उपयोग नहीं कर सकता है।



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



पाठ क्षेत्र UITextField



के इनपुट को मान्य करने के लिए रणनीतियों के रूप में डेटा को मान्य करने के लिए कई वर्गों को डिज़ाइन और कार्यान्वित करेंगे।



एक रणनीति पैटर्न क्या है?



इस पैटर्न में मुख्य भूमिकाओं में से एक रणनीति वर्ग द्वारा निभाई जाती है, जो सभी समर्थित एल्गोरिदम के लिए एक सामान्य इंटरफ़ेस की घोषणा करती है। रणनीतियों के विशिष्ट वर्ग भी हैं जो रणनीति इंटरफ़ेस का उपयोग करके एल्गोरिदम को लागू करते हैं। एक संदर्भ वस्तु को एक विशिष्ट रणनीति वस्तु के उदाहरण का उपयोग करके कॉन्फ़िगर किया गया है। एक संदर्भ ऑब्जेक्ट एक विशेष रणनीति वर्ग में परिभाषित एल्गोरिथ्म को लागू करने के लिए रणनीति इंटरफ़ेस का उपयोग करता है। उनके संबंध को चित्र 191 में वर्ग आरेख में चित्रित किया गया है।



छवि

चित्र 19-1। कक्षा संरचना पैटर्न रणनीति



एक समूह या संबंधित एल्गोरिदम के पदानुक्रम, ConcreteStrategy



क्लासेस (ए, बी और सी) के रूप में एक सामान्य algorithmInterface



साझा algorithmInterface



, इसलिए Context



एक ही इंटरफ़ेस का उपयोग करके एल्गोरिदम के विभिन्न संस्करणों तक पहुंच सकता है।



नोट। रणनीति पैटर्न : एल्गोरिदम के एक परिवार को परिभाषित करता है, उनमें से प्रत्येक को एन्क्रिप्ट करता है और उन्हें विनिमेय बनाता है। रणनीति उन ग्राहकों को स्वतंत्र रूप से बदलने की अनुमति देती है जो उनका उपयोग करते हैं। *



गोफ के डिज़ाइन पैटर्न (एडिसन-वेस्ले, 1994) में दी गई प्रारंभिक परिभाषा।



एक Context



उदाहरण रनटाइम पर विभिन्न ConcreteStrategy



ऑब्जेक्ट्स का उपयोग करके कॉन्फ़िगर किया जा सकता है। इसे Context



वस्तु के "इनसाइड" में बदलाव माना जा सकता है, क्योंकि अंदर से परिवर्तन होते हैं। डेकोरेटर (अध्याय 16, डेकोरेटर पैटर्न और मेरा पिछला लेख देखें), इसके विपरीत, ऑब्जेक्ट की "त्वचा" को बदलते हैं, क्योंकि संशोधनों को बाहर से डॉक किया गया है। कृपया अंतर पर अधिक विस्तृत जानकारी के लिए अध्याय 16 (पिछले लेख) में "इनसाइड" को बदलने की तुलना में किसी वस्तु की "त्वचा" बदलना "खंड" का संदर्भ लें।



मॉडल-व्यू-कंट्रोलर में रणनीति पैटर्न



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



रणनीति पैटर्न का उपयोग कब उचित है?



इस पैटर्न का उपयोग निम्नलिखित मामलों में उचित है:





UITextField वर्ग का उपयोग करके डेटा सत्यापन रणनीतियों का उपयोग करना



आइए आवेदन में रणनीति पैटर्न के कार्यान्वयन का एक सरल उदाहरण बनाएं। मान लें कि हमें अपने आवेदन में कुछ UITextField



ऑब्जेक्ट की आवश्यकता है जो उपयोगकर्ता इनपुट को स्वीकार करता है; हम बाद में अपने आवेदन में इनपुट परिणामों का उपयोग करेंगे। हमारे पास एक टेक्स्ट इनपुट फ़ील्ड है जो केवल अक्षरों को स्वीकार करता है, वह है, - a - z या A - Z, और इसके अलावा हमारे पास एक फ़ील्ड है जो केवल संख्यात्मक डेटा को स्वीकार करता है, वह है, 0–9। यह सुनिश्चित करने के लिए कि फ़ील्ड में इनपुट सही है, उनमें से प्रत्येक को उपयोगकर्ता के संपादन समाप्त करने के बाद किसी तरह की ऑन-साइट डेटा सत्यापन प्रक्रिया शुरू करने की आवश्यकता है।



हम आवश्यक डेटा सत्यापन को प्रतिनिधि ऑब्जेक्ट विधि UITextField



, textFieldDidEndEditing:



में डाल सकते हैं textFieldDidEndEditing:



एक UITextField



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



पैरामीटर के रूप में) के इनपुट पर एक लिंक स्वीकार करती है, लेकिन यह दो वस्तुओं में से कौन सी है?



ट्रेजिया पैटर्न के बिना, हम एक कोड में आए होंगे जैसे कि लिस्टिंग 19-1 में दिखाया गया है।



लिस्टिंग 19–1। विशिष्ट UITextField सामग्री डेलिगेशन स्क्रिप्ट को प्रतिनिधि विधि टेक्स्टFieldDidEndEditing में

 - (void)textFieldDidEndEditing:(UITextField *)textField { if (textField == numericTextField) { //  [textField text]  , //    } else if (textField == alphaTextField) { //  [textField text]  , //      } }
      
      







बेशक, अलग-अलग डेटा के लिए अधिक इनपुट फ़ील्ड होने पर अधिक सशर्त बयान हो सकते हैं। यदि हम इन सभी सशर्त अभिव्यक्तियों से छुटकारा पा लेते हैं, तो हम कोड को अधिक प्रबंधनीय बना सकते हैं, जो भविष्य में कोड के समर्थन से हमारे जीवन को सरल बना सकते हैं।



युक्ति: यदि आपके कोड में बहुत सारे सशर्त वक्तव्य हैं, तो इसका मतलब यह हो सकता है कि आपको उन्हें फिर से बनाने और रणनीति की अलग-अलग वस्तुओं में अलग करने की आवश्यकता है।



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



का मान लौटाती है और चेक विफल होने पर NSError



का एक उदाहरण देता है। लौटा हुआ NSError



ऑब्जेक्ट यह निर्धारित करने में मदद करेगा कि सत्यापन सफल क्यों नहीं हुआ। चूंकि डिजिटल और अक्षर दोनों इनपुट का सत्यापन एक-दूसरे से संबंधित है (उनके पास एक ही प्रकार के इनपुट और आउटपुट हैं), उन्हें एक इंटरफ़ेस से जोड़ा जा सकता है। कक्षाओं का हमारा सेट चित्र 19-2 में कक्षा आरेख में दिखाया गया है।



छवि

चित्र 19–2। वर्ग आरेख CustomTextField और उससे जुड़ी रणनीतियों के बीच संबंध को दर्शाता है।



हम इस इंटरफ़ेस को एक प्रोटोकॉल के रूप में नहीं, बल्कि एक सार आधार वर्ग के रूप में घोषित करेंगे। इस मामले में अमूर्त आधार वर्ग अधिक सुविधाजनक है, क्योंकि यह सभी ठोस वर्गों की रणनीतियों के लिए व्यवहार को फिर से परिभाषित करना आसान है। हमारा सार आधार वर्ग लिस्टिंग 19-2 की तरह दिखेगा।



लिस्टिंग 19–2। InputValidator.h में एक InputValidator वर्ग की घोषणा

 @interface InputValidator : NSObject { } //      - (BOOL) validateInput:(UITextField *)input error:(NSError **) error; @end
      
      







UITextField



validateInput: error:



विधि एक इनपुट पैरामीटर के रूप में UITextField



संदर्भ को स्वीकार करता है, इसलिए यह इनपुट क्षेत्र में सब कुछ जांच सकता है और चेक के परिणामस्वरूप BOOL



मान लौटाता है। विधि एक NSError



को पॉइंटर के संदर्भ को भी स्वीकार करती है। जब किसी प्रकार की त्रुटि हुई (अर्थात, विधि इनपुट की शुद्धता को सत्यापित नहीं कर सकी), तो विधि NSError



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



इस पद्धति का डिफ़ॉल्ट कार्यान्वयन केवल त्रुटि सूचक को nil



सेट करता है और NO



वापस करता है, जैसा कि 19-3 लिस्टिंग में दिखाया गया है।



लिस्टिंग 19-3। InputValidator.m में InputValidator वर्ग का डिफ़ॉल्ट कार्यान्वयन

 #import "InputValidator.h" @implementation InputValidator //      - (BOOL) validateInput:(UITextField *)input error:(NSError **) error { if (error) { *error = nil; } return NO; } @end
      
      







हमने इनपुट पैरामीटर के रूप में NSString



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



प्रकार के इनपुट पैरामीटर के साथ UITextField



हम दो दृष्टिकोणों को जोड़ सकते हैं। हमारी स्कैन ऑब्जेक्ट टेक्स्ट फ़ील्ड के प्रारंभिक मूल्य (उदाहरण के लिए, गलत वर्णों को हटाकर) को बदलने में सक्षम होगी या इसे बदलने के बिना केवल मूल्य देख सकती है।



एक और सवाल यह है कि अगर चेक फेल हो जाता है तो हम सिर्फ NSException



क्यों नहीं फेंकते? ऐसा इसलिए है क्योंकि अपने स्वयं के अपवाद को फेंकना और कोको टच फ्रेम में एक कोशिश-कैच ब्लॉक में इसे पकड़ना एक बहुत ही संसाधन-गहन ऑपरेशन है और अनुशंसित नहीं है (लेकिन कोशिश-कैच सिस्टम अपवाद एक पूरी तरह से अलग मामला है)। कोको टच डेवलपर गाइड में सिफारिश की गई NSError



वस्तु को वापस करना अपेक्षाकृत सस्ता है। यदि हम कोकोआ टच फ्रेमवर्क प्रलेखन को देखते हैं, तो हम देखेंगे कि कई एपीआई ऐसे हैं जो कुछ असामान्य स्थिति होने पर NSError



उदाहरण देते हैं। एक सामान्य उदाहरण NSFileManager



विधियों में से एक है, (BOOL)moveItemAtPath:(NSString *)srcPath toPath:(NSString *)dstPath error:(NSError **)error



। यदि NSFileManager



फ़ाइल को एक स्थान से दूसरे स्थान पर ले जाने का प्रयास करता है, तो एक त्रुटि होती है, यह एक नया NSError



उदाहरण बनाएगा जो समस्या का वर्णन करता है। कॉलिंग विधि त्रुटियों को आगे संभालने के लिए लौटे NSError



ऑब्जेक्ट में निहित जानकारी का उपयोग कर सकती है। इस प्रकार, हमारी विधि में NSError



ऑब्जेक्ट का लक्ष्य काम के इनकार के बारे में जानकारी प्रदान करना है।



अब हमने परिभाषित किया है कि एक अच्छे इनपुट सत्यापन वर्ग को कैसे व्यवहार करना चाहिए। अब हम एक वास्तविक समीक्षक बनाना शुरू कर सकते हैं। आइए पहले इनपुट नंबर के लिए एक बनाएं, जैसा कि लिस्टिंग 19-4 में दिखाया गया है।



लिस्टिंग 19-4। NumericInputValidator.h में एक NumericInputValidator वर्ग की घोषणा करना

 #import "InputValidator.h" @interface NumericInputValidator : InputValidator { } //  ,  ,     // ,   0-9 - (BOOL) validateInput:(UITextField *)input error:(NSError **) error; @end
      
      







NumericInputValidator



अमूर्त आधार वर्ग NumericInputValidator



विरासत में मिला है और इसकी NumericInputValidator



को ओवरराइड करता है validateInput: error:



विधि। हम इस उपवर्ग को लागू करने या फिर से परिभाषित करने पर जोर देने के लिए फिर से विधि की घोषणा करते हैं। यह आवश्यक नहीं है, लेकिन अच्छा अभ्यास है।



विधि का कार्यान्वयन 19-5 की सूची में दिखाया गया है।



लिस्टिंग 19-5। NumericInputValidator.m में NumericInputValidator वर्ग का कार्यान्वयन

 #import "NumericInputValidator.h" @implementation NumericInputValidator - (BOOL) validateInput:(UITextField *)input error:(NSError**) error { NSError *regError = nil; NSRegularExpression *regex = [NSRegularExpression regularExpressionWithPattern:@"^[0-9]*$" options:NSRegularExpressionAnchorsMatchLines error:®Error]; NSUInteger numberOfMatches = [regex numberOfMatchesInString:[input text] options:NSMatchingAnchored range:NSMakeRange(0, [[input text] length])]; //   , //     NO if (numberOfMatches == 0) { if (error != nil) { NSString *description = NSLocalizedString(@"Input Validation Failed", @""); NSString *reason = NSLocalizedString(@"The input can contain only numerical values", @""); NSArray *objArray = [NSArray arrayWithObjects:description, reason, nil]; NSArray *keyArray = [NSArray arrayWithObjects:NSLocalizedDescriptionKey, NSLocalizedFailureReasonErrorKey, nil]; NSDictionary *userInfo = [NSDictionary dictionaryWithObjects:objArray forKeys:keyArray]; *error = [NSError errorWithDomain:InputValidationErrorDomain code:1001 userInfo:userInfo]; } return NO; } return YES; } @end
      
      







validateInput:error:



का कार्यान्वयन validateInput:error:



विधि मुख्य रूप से दो पहलुओं पर केंद्रित है:



  1. यह पहले बनाए गए NSRegularExpression



    ऑब्जेक्ट के साथ इनपुट फ़ील्ड में संख्यात्मक डेटा के मैचों की संख्या की जांच करता है। हमारे द्वारा उपयोग की जाने वाली नियमित अभिव्यक्ति "^ [0–9] * $" है। इसका अर्थ है कि संपूर्ण पंक्ति की शुरुआत से ("^" द्वारा इंगित) और अंत ("$" द्वारा दर्शाया गया है), सेट से 0 या अधिक वर्ण ("*" द्वारा) होना चाहिए जिसमें केवल अंक ("0/9) द्वारा इंगित किया गया हो। ")।
  2. यदि कोई मेल नहीं हैं, तो वह एक नया NSError



    ऑब्जेक्ट बनाता है जिसमें संदेश "इनपुट में केवल संख्यात्मक मान हो सकते हैं" और इसे NSError



    एक इनपुट पॉइंटर को असाइन करता है। फिर यह अंततः प्रकार BOOL



    का मान लौटाता है जो ऑपरेशन की सफलता या विफलता का संकेत देता है। त्रुटि विशेष कोड 1001 के साथ जुड़ी हुई है और InputValidator



    वर्ग के हेडर फाइल में परिभाषित त्रुटि डोमेन के विशेष मूल्य के रूप में नीचे दिखाया गया है:

     static NSString * const InputValidationErrorDomain = @"InputValidationErrorDomain";
          
          





NumericInputValidator



वर्ग का भाई, जो इनपुट में केवल अक्षरों की जांच करता है, जिसे AlphaInputValidator



कहा जाता है, में इनपुट फ़ील्ड की सामग्री की जाँच के लिए एक समान एल्गोरिथ्म होता है। AlphaInputValidator



के समान विधि को ओवरराइड करता है। जाहिर है, यह एल्गोरिथ्म पुष्टि करता है कि इनपुट स्ट्रिंग में केवल अक्षर होते हैं, जैसा कि लिस्टिंग 19-6 में दिखाया गया है।



लिस्टिंग 19-6। AlphaInputValidator.m में AlphaInputValidator वर्ग का कार्यान्वयन

 #import "AlphaInputValidator.h" @implementation AlphaInputValidator - (BOOL) validateInput:(UITextField *)input error:(NSError**) error { NSError *regError = nil; NSRegularExpression *regex = [NSRegularExpression regularExpressionWithPattern:@"^[a-zA-Z]*$" options:NSRegularExpressionAnchorsMatchLines error:®Error]; NSUInteger numberOfMatches = [regex numberOfMatchesInString:[input text] options:NSMatchingAnchored range:NSMakeRange(0, [[input text] length])]; //   , //     NO if (numberOfMatches == 0) { if (error != nil) { NSString *description = NSLocalizedString(@"Input Validation Failed", @""); NSString *reason = NSLocalizedString(@"The input can contain only letters", @""); NSArray *objArray = [NSArray arrayWithObjects:description, reason, nil]; NSArray *keyArray = [NSArray arrayWithObjects:NSLocalizedDescriptionKey, NSLocalizedFailureReasonErrorKey, nil]; NSDictionary *userInfo = [NSDictionary dictionaryWithObjects:objArray forKeys:keyArray]; *error = [NSError errorWithDomain:InputValidationErrorDomain code:1002 userInfo:userInfo]; } return NO; } return YES; } @end
      
      







हमारा AlphaInputValidator



वर्ग भी AlphaInputValidator



एक प्रकार AlphaInputValidator



और AlphaInputValidator



विधि validateInput:



लागू करता है। इसके पास एक भाई-जैसा, NumericInputValidator



, कोड संरचना और एल्गोरिदम है, सिवाय इसके कि यह NSRegularExpression



ऑब्जेक्ट में एक अलग नियमित अभिव्यक्ति का उपयोग करता है, और त्रुटि कोड और संदेश पत्र सत्यापन के लिए विशिष्ट हैं। नियमित अभिव्यक्ति जो हम अक्षरों का परीक्षण करने के लिए उपयोग करते हैं, "^ [a-zA-Z] * $" है। यह उनके साथी संख्यात्मक सत्यापन के लिए एक अभिव्यक्ति की तरह दिखता है, सिवाय इसके कि वैध वर्णों के सेट में निचले और ऊपरी दोनों प्रकार के अक्षर होते हैं। जैसा कि हम देख सकते हैं, दोनों संस्करणों में बहुत सारे डुप्लिकेट कोड हैं। दोनों एल्गोरिदम में एक समान संरचना है; आप एक टेंपलेट विधि (अध्याय 18 देखें) को एक सार आधार वर्ग में संरचना को रिफ्लेक्टर कर सकते हैं। InputValidator



विशिष्ट उपवर्ग InputValidator



एल्गोरिथ्म में अद्वितीय जानकारी वापस करने के लिए InputValidator



में परिभाषित आदिम परिचालनों को ओवरराइड कर सकते हैं - उदाहरण के लिए, NSError



ऑब्जेक्ट की नियमित अभिव्यक्ति और विभिन्न निर्माण विशेषताएँ, आदि। मैं इसे आपको एक अभ्यास के रूप में छोड़ दूँगा।



अब हमारे पास पहले से ही सत्यापन कक्षाएं हैं जो आवेदन में उपयोग के लिए तैयार हैं। हालांकि, UITextFiel



d उनके बारे में नहीं जानता है, इसलिए हमें UITextField



अपने संस्करण की आवश्यकता है, जो सब कुछ समझता है। हम UITextField



का एक उपवर्ग बनाएंगे जिसमें InputValidator



और validate



विधि का संदर्भ होता है, जैसा कि लिस्टिंग 19-7 में दिखाया गया है।



लिस्टिंग 19-7। CustomTextField वर्ग की घोषणा CustomTextField.h में

 #import "InputValidator.h" @interface CustomTextField : UITextField { @private InputValidator *inputValidator_; } @property (nonatomic, retain) IBOutlet InputValidator *inputValidator; - (BOOL) validate; @end
      
      







CustomTextField



में एक ऐसी संपत्ति होती है जो InputValidator



संदर्भ रखती है। जब इसकी validate



विधि को बुलाया जाता है, तो यह सत्यापन शुरू करने के लिए InputValidator



संदर्भ का उपयोग करता है। हम इसे 198 की लिस्टिंग में दिखाए गए कार्यान्वयन में देख सकते हैं।



लिस्टिंग 19-8। CustomTextField.m में CustomTextField वर्ग कार्यान्वयन

 #import "CustomTextField.h" @implementation CustomTextField @synthesize inputValidator=inputValidator_; - (BOOL) validate { NSError *error = nil; BOOL validationResult = [inputValidator_ validateInput:self error:&error]; if (!validationResult) { UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:[error localizedDescription] message:[error localizedFailureReason] delegate:nil cancelButtonTitle:NSLocalizedString(@"OK", @"") otherButtonTitles:nil]; [alertView show]; [alertView release]; } return validationResult; } - (void) dealloc { [inputValidator_ release]; [super dealloc]; } @end
      
      







संदेश [inputValidator_ validateInput:self

error:&error]




validate



विधि में भेजा गया है [inputValidator_ validateInput:self

error:&error]




[inputValidator_ validateInput:self

error:&error]




लिंक inputValidator_



। पैटर्न की सुंदरता यह है कि CustomTextField



को यह जानने की आवश्यकता नहीं है कि यह किस प्रकार के InputValidator



का उपयोग करता है या एल्गोरिथ्म का कोई विवरण। इसलिए, यदि भविष्य में हम कुछ नए InputValidator



जोड़ते हैं, तो CustomTextField



ऑब्जेक्ट उसी तरह से नए InputValidator



उपयोग करेगा।



लिहाजा, पूरी तैयारी की गई है। मान लीजिए कि क्लाइंट एक UIViewController



है जो UITextFieldDelegate



प्रोटोकॉल को लागू करता है और इसमें CustomTextField



प्रकार के दो IBOutlets



शामिल हैं, जैसा कि लिस्टिंग 19-9 में दिखाया गया है।



लिस्टिंग 19-9। StrategyViewController.h में StrategyViewController वर्ग घोषणा

 #import "NumericInputValidator.h" #import "AlphaInputValidator.h" #import "CustomTextField.h" @interface StrategyViewController : UIViewController <UITextFieldDelegate> { @private CustomTextField *numericTextField_; CustomTextField *alphaTextField_; } @property (nonatomic, retain) IBOutlet CustomTextField *numericTextField; @property (nonatomic, retain) IBOutlet CustomTextField *alphaTextField; @end
      
      







हमने नियंत्रक प्रतिनिधि विधि (void)textFieldDidEndEditing:(UITextField *)textField



लागू करने का निर्णय लिया। (void)textFieldDidEndEditing:(UITextField *)textField



और वहाँ जाँच डालें। इस क्षेत्र को हर बार इनपुट क्षेत्र में मूल्य में परिवर्तन कहा जाएगा और फोकस खो जाएगा। जब उपयोगकर्ता टाइप करना समाप्त कर देता है, तो हमारा CustomTextField



वर्ग इस प्रतिनिधि पद्धति को कॉल करेगा, जैसा कि सूची 19-10 में दिखाया गया है।



लिस्टिंग 19-10। प्रतिनिधि कोड टेक्स्ट में ग्राहक कोड परिभाषित किया गया है ।FieldDidEndEditing :, जो एक रणनीति ऑब्जेक्ट (InputValidator) का उपयोग करके CustomTextField के एक उदाहरण को मान्य करता है

 @implementation StrategyViewController @synthesize numericTextField, alphaTextField; // ... //    // ... #pragma mark - #pragma mark UITextFieldDelegate methods - (void)textFieldDidEndEditing:(UITextField *)textField { if ([textField isKindOfClass:[CustomTextField class]]) { [(CustomTextField*)textField validate]; } } @end
      
      







textFieldDidEndEditing:



कॉल करते समय textFieldDidEndEditing:



जब खेतों में से किसी एक में संपादन पूरा हो जाता है, तो विधि यह textField



कि textField



ऑब्जेक्ट CustomTextField



वर्ग का है। यदि ऐसा है, तो वह प्रवेश किए गए पाठ की जांच की प्रक्रिया शुरू करने के लिए उसे एक validate



संदेश भेजता है। जैसा कि हम देख सकते हैं, हमें अब इन सशर्त बयानों की आवश्यकता नहीं है। इसके बजाय, हमारे पास समान उद्देश्य के लिए बहुत सरल कोड है। अतिरिक्त जाँच के अपवाद के साथ कि textField



एक CustomTextField



, अधिक जटिल कुछ भी नहीं है।



लेकिन एक पल रुकिए। कुछ बहुत अच्छा नहीं लगता है। हम कैसे कर सकते हैं सही InputValidator numericTextField_



इंस्टेंसेस के InputValidator numericTextField_



और alphaTextField_



को StrategyViewController



में परिभाषित? दोनों इनपुट फील्ड्स को IBOutlet



को Listing 199 में घोषित किया गया है। हम उन्हें इंटरफ़ेस बिल्डर व्यू कंट्रोलर में IBOutlet



माध्यम से चुन सकते हैं, जैसा कि हम अन्य बटन और बहुत कुछ के साथ करते हैं। इसी तरह, लिस्टिंग inputValidator



में CustomTextField



वर्ग की घोषणा में, इसकी inputValidator



संपत्ति एक IBOutlet



भी है, जिसका अर्थ है कि हम inputValidator



एक उदाहरण इंटरफ़ेस इंटरफ़ेस में एक *TextField



ऑब्जेक्ट को भी असाइन कर सकते हैं।इस प्रकार, सब कुछ इंटरफ़ेस बिल्डर संदर्भ लिंक का उपयोग करके निर्माण किया जा सकता है यदि आप कुछ वर्ग गुणों को घोषित करते हैं IBOutlet



। कस्टम इंटरफ़ेस बिल्डर ऑब्जेक्ट्स का उपयोग करने के तरीके के बारे में अधिक विस्तृत चर्चा के लिए, CoordinatingController



अध्याय 11 में "इंटरफ़ेस बिल्डर का उपयोग करना" देखें , जो मध्यस्थ पैटर्न के बारे में बात करता है।



निष्कर्ष



इस अध्याय में, हमने रणनीति पैटर्न की अवधारणाओं और विभिन्न संबंधित एल्गोरिदम का उपयोग करने के लिए ग्राहकों के लिए इस पैटर्न का उपयोग करने के तरीके पर चर्चा की। एक कस्टम एक के लिए इनपुट जांच के कार्यान्वयन का एक उदाहरण UITextField



दिखाता है कि चेक के विभिन्न वर्ग किसी वस्तु के "आंतरिक" को कैसे बदल सकते हैं। रणनीति पैटर्न कुछ हद तक डेकोरेटर पैटर्न (अध्याय 16 और मेरे पिछले लेख) के समान है। सज्जाकार बाहर से किसी वस्तु के व्यवहार का विस्तार करते हैं जबकि विभिन्न रणनीतियों को वस्तु के भीतर समझाया जाता है। जैसा कि वे कहते हैं, सज्जाकार वस्तु की "त्वचा" को बदलते हैं, और रणनीतियों - "अंदरूनी"।



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



All Articles