एक डिज़ाइन पैटर्न एक टेम्प्लेट है जो सॉफ़्टवेयर डिज़ाइन में सामान्य रूप से होने वाली समस्या को हल करता है।
राज्य पैटर्न एक व्यवहारिक पैटर्न है जो किसी वस्तु को उसके आंतरिक स्थिति में परिवर्तन होने पर उसके व्यवहार को बदलने देता है।
यहां आप सीखेंगे कि टाइपस्क्रिप्ट में स्टेट पैटर्न का उपयोग कैसे करें।
राज्य पैटर्न क्या है?
राज्य डिजाइन पैटर्न एक परिमित-राज्य मशीन से निकटता से संबंधित है, जो एक प्रोग्राम का वर्णन करता है जो मौजूद है परिमित किसी भी समय राज्यों की संख्या और प्रत्येक राज्य के भीतर अलग-अलग व्यवहार करता है।
सीमित, पूर्वनिर्धारित नियम—संक्रमण—हैं जो उन अन्य राज्यों को नियंत्रित करते हैं जिन पर प्रत्येक राज्य स्विच कर सकता है।
संदर्भ के लिए, एक ऑनलाइन स्टोर में, यदि किसी ग्राहक का शॉपिंग ऑर्डर "वितरित" किया गया है, तो इसे "रद्द" नहीं किया जा सकता क्योंकि यह पहले ही "वितरित" हो चुका है। "वितरित" और "रद्द" आदेश की परिमित अवस्थाएँ हैं, और आदेश अपनी स्थिति के आधार पर अलग-अलग व्यवहार करेगा।
राज्य पैटर्न वर्ग बनाता है प्रत्येक संभावित स्थिति के लिए, प्रत्येक वर्ग में निहित राज्य-विशिष्ट व्यवहार के साथ।
एक उदाहरण राज्य-आधारित अनुप्रयोग
उदाहरण के लिए, मान लें कि आप एक ऐसा एप्लिकेशन बना रहे हैं जो किसी प्रकाशन कंपनी के लिए किसी लेख की स्थिति को ट्रैक करता है। एक लेख या तो लंबित अनुमोदन हो सकता है, एक लेखक द्वारा तैयार किया जा सकता है, एक संपादक द्वारा संपादित किया जा सकता है, या प्रकाशित किया जा सकता है। प्रकाशित होने वाले लेख की ये परिमित अवस्थाएँ हैं; प्रत्येक अनूठी स्थिति के भीतर, लेख अलग तरह से व्यवहार करता है।
आप नीचे दिए गए स्टेट डायग्राम के साथ आर्टिकल एप्लिकेशन के विभिन्न राज्यों और बदलावों की कल्पना कर सकते हैं:
इस परिदृश्य को कोड में कार्यान्वित करते हुए, आपको पहले आलेख के लिए एक इंटरफ़ेस घोषित करना होगा:
इंटरफेसलेख इंटरफ़ेस{
आवाज़ का उतार-चढ़ाव(): खालीपन;
प्रारूप(): खालीपन;
संपादन करना(): खालीपन;
प्रकाशित करें (): खालीपन;
}
इस इंटरफ़ेस में एप्लिकेशन की सभी संभावित स्थितियाँ होंगी।
अगला, एक एप्लिकेशन बनाएं जो सभी इंटरफ़ेस विधियों को लागू करता है:
// आवेदन
कक्षालेखऔजारलेख इंटरफ़ेस{
निर्माता() {
यहशो करंटस्टेट ();
}निजीshowCurrentState(): खालीपन{
//...
}जनताआवाज़ का उतार-चढ़ाव(): खालीपन{
//...
}जनताप्रारूप(): खालीपन{
//...
}जनतासंपादन करना(): खालीपन{
//...
}
जनताप्रकाशित(): खालीपन{
//...
}
}
निजी showCurrentState विधि एक उपयोगी विधि है। यह ट्यूटोरियल इसका उपयोग यह दिखाने के लिए करता है कि प्रत्येक राज्य में क्या होता है। यह राज्य पैटर्न का एक आवश्यक हिस्सा नहीं है।
राज्य संक्रमण को संभालना
अगला, आपको राज्य के बदलावों को संभालने की आवश्यकता होगी। आपके आवेदन वर्ग में राज्य संक्रमण को संभालने के लिए बहुतों की आवश्यकता होगी सशर्त बयान. इसके परिणामस्वरूप दोहराए जाने वाले कोड को पढ़ना और बनाए रखना कठिन होगा। इस समस्या को हल करने के लिए, आप प्रत्येक राज्य के लिए संक्रमण तर्क को अपनी कक्षा में सौंप सकते हैं।
इससे पहले कि आप प्रत्येक राज्य वर्ग को लिखें, आपको यह सुनिश्चित करने के लिए एक अमूर्त आधार वर्ग बनाना चाहिए कि किसी अमान्य स्थिति में बुलाए गए किसी भी तरीके से कोई त्रुटि हो।
उदाहरण के लिए:
अमूर्तकक्षाआर्टिकलस्टेटऔजारलेख इंटरफ़ेस{
पिच (): आर्टिकलस्टेट {
फेंकनानयागलती("अमान्य ऑपरेशन: कार्य नहीं कर सकता में वर्तमान स्थिति");
}मसौदा (): आर्टिकलस्टेट {
फेंकनानयागलती("अमान्य ऑपरेशन: कार्य नहीं कर सकता में वर्तमान स्थिति");
}संपादित करें (): आर्टिकलस्टेट {
फेंकनानयागलती("अमान्य ऑपरेशन: कार्य नहीं कर सकता में वर्तमान स्थिति");
}
प्रकाशित (): आर्टिकलस्टेट {
फेंकनानयागलती("अमान्य ऑपरेशन: कार्य नहीं कर सकता में वर्तमान स्थिति");
}
}
उपरोक्त बेस क्लास में, प्रत्येक विधि एक त्रुटि फेंकती है। अब, आपको विशिष्ट वर्ग बनाकर प्रत्येक विधि को ओवरराइड करना होगा का विस्तार प्रत्येक राज्य के लिए आधार वर्ग। प्रत्येक विशिष्ट वर्ग में राज्य-विशिष्ट तर्क होंगे।
प्रत्येक एप्लिकेशन में एक निष्क्रिय स्थिति होती है, जो एप्लिकेशन को आरंभ करती है। इस एप्लिकेशन के लिए निष्क्रिय स्थिति एप्लिकेशन को पर सेट कर देगी प्रारूप राज्य।
उदाहरण के लिए:
कक्षालंबित ड्राफ्टस्टेटका विस्तारआर्टिकलस्टेट{
पिच (): आर्टिकलस्टेट {
वापस करनानया ड्राफ्टस्टेट ();
}
}
आवाज़ का उतार-चढ़ाव उपरोक्त वर्ग में विधि वर्तमान स्थिति को सेट करके एप्लिकेशन को प्रारंभ करती है ड्राफ्टस्टेट.
अगला, बाकी तरीकों को ओवरराइड करें जैसे:
कक्षाड्राफ्टस्टेटका विस्तारआर्टिकलस्टेट{
मसौदा (): आर्टिकलस्टेट {
वापस करनानया एडिटिंगस्टेट ();
}
}
यह कोड ओवरराइड करता है प्रारूप विधि और का एक उदाहरण देता है एडिटिंगस्टेट.
कक्षाएडिटिंगस्टेटका विस्तारआर्टिकलस्टेट{
संपादित करें (): आर्टिकलस्टेट {
वापस करनानया प्रकाशित स्थिति ();
}
}
उपरोक्त कोड ब्लॉक ओवरराइड करता है संपादन करना विधि और का एक उदाहरण देता है PublishedState.
कक्षाPublishedStateका विस्तारआर्टिकलस्टेट{
प्रकाशित (): आर्टिकलस्टेट {
वापस करनानया लंबित ड्राफ्टस्टेट ();
}
}
उपरोक्त कोड ब्लॉक ओवरराइड करता है प्रकाशित विधि और एप्लिकेशन को वापस उसकी निष्क्रिय अवस्था में रखता है, लंबित ड्राफ्टस्टेट.
फिर, आपको एक निजी चर के माध्यम से वर्तमान स्थिति को संदर्भित करके एप्लिकेशन को अपनी स्थिति को आंतरिक रूप से बदलने की अनुमति देने की आवश्यकता है। आप इसे अपने एप्लिकेशन वर्ग के अंदर निष्क्रिय अवस्था को आरंभ करके और मान को एक निजी चर में संग्रहीत करके कर सकते हैं:
निजी राज्य: अनुच्छेद राज्य = नया लंबित ड्राफ्टस्टेट ();
अगला, अद्यतन करें showCurrentState वर्तमान स्थिति मान को प्रिंट करने की विधि:
निजीshowCurrentState(): खालीपन{
सांत्वना देना।लकड़ी का लट्ठा(यह।राज्य);
}
showCurrentState विधि एप्लिकेशन की वर्तमान स्थिति को कंसोल पर लॉग करती है।
अंत में, अपने प्रत्येक एप्लिकेशन के तरीकों में निजी चर को वर्तमान स्थिति उदाहरण में पुन: असाइन करें।
उदाहरण के लिए, अपने एप्लिकेशन अपडेट करें आवाज़ का उतार-चढ़ाव नीचे दिए गए कोड ब्लॉक की विधि:
जनताआवाज़ का उतार-चढ़ाव(): खालीपन{
यहराज्य = यह.स्टेट.पिच ();
यहशो करंटस्टेट ();
}
उपरोक्त कोड ब्लॉक में, आवाज़ का उतार-चढ़ाव विधि स्थिति को वर्तमान स्थिति से पिच स्थिति में बदलती है।
इसी तरह, अन्य सभी विधियां वर्तमान आवेदन स्थिति से राज्य को उनके संबंधित राज्यों में बदल देंगी।
नीचे दिए गए कोड ब्लॉक में अपनी एप्लिकेशन विधियों को अपडेट करें:
प्रारूप तरीका:
जनताप्रारूप(): खालीपन{
यहराज्य = यह.स्टेट.ड्राफ्ट ();
यहशो करंटस्टेट ();
}
संपादन करना तरीका:
जनतासंपादन करना(): खालीपन{
यहराज्य = यहराज्य संपादित करें ();
यहशो करंटस्टेट ();
}
और यह प्रकाशित तरीका:
जनताप्रकाशित(): खालीपन{
यहराज्य = यहराज्य.प्रकाशित ();
यहशो करंटस्टेट ();
}
समाप्त आवेदन का उपयोग करना
आपका समाप्त आवेदन वर्ग नीचे दिए गए कोड ब्लॉक के समान होना चाहिए:
// आवेदन
कक्षालेखऔजारलेख इंटरफ़ेस{
निजी राज्य: अनुच्छेद राज्य = नया लंबित ड्राफ्टस्टेट ();निर्माता() {
यहशो करंटस्टेट ();
}निजीshowCurrentState(): खालीपन{
सांत्वना देना।लकड़ी का लट्ठा(यह।राज्य);
}जनताआवाज़ का उतार-चढ़ाव(): खालीपन{
यहराज्य = यह.स्टेट.पिच ();
यहशो करंटस्टेट ();
}जनताप्रारूप(): खालीपन{
यहराज्य = यह.स्टेट.ड्राफ्ट ();
यहशो करंटस्टेट ();
}जनतासंपादन करना(): खालीपन{
यहराज्य = यहराज्य संपादित करें ();
यहशो करंटस्टेट ();
}
जनताप्रकाशित(): खालीपन{
यहराज्य = यहराज्य.प्रकाशित ();
यहशो करंटस्टेट ();
}
}
आप विधियों को सही क्रम में कॉल करके राज्य के संक्रमण का परीक्षण कर सकते हैं। उदाहरण के लिए:
कॉन्स्ट डॉक्स = नया लेख(); // लंबित ड्राफ्टस्टेट: {}
डॉक्स.पिच (); // ड्राफ्टस्टेट: {}
डॉक्स.ड्राफ्ट (); // एडिटिंगस्टेट: {}
डॉक्स.एडिट (); // प्रकाशित स्थिति: {}
डॉक्स.प्रकाशित (); // लंबित ड्राफ्टस्टेट: {}
उपरोक्त कोड ब्लॉक काम करता है क्योंकि एप्लिकेशन के राज्य उचित रूप से परिवर्तित हो गए हैं।
यदि आप राज्य को ऐसे तरीके से बदलने का प्रयास करते हैं जिसकी अनुमति नहीं है, उदाहरण के लिए, पिच स्थिति से संपादन स्थिति में, एप्लिकेशन एक त्रुटि फेंकेगा:
कॉन्स्ट डॉक्स = नया लेख(); // लंबित ड्राफ्टस्टेट: {}
डॉक्स.पिच () // ड्राफ्टस्टेट: {}
डॉक्स.एडिट () // अमान्य ऑपरेशन: वर्तमान स्थिति में कार्य नहीं कर सकता
आपको इस पैटर्न का उपयोग केवल तभी करना चाहिए जब:
- आप एक ऐसी वस्तु बना रहे हैं जो अपनी वर्तमान स्थिति के आधार पर भिन्न व्यवहार करती है।
- वस्तु में कई अवस्थाएँ होती हैं।
- राज्य-विशिष्ट व्यवहार अक्सर बदलता रहता है।
राज्य पैटर्न के लाभ और व्यापार-नापसंद
यह पैटर्न भारी सशर्त बयानों को समाप्त करता है और एकल जिम्मेदारी और खुले/बंद सिद्धांतों को बनाए रखता है। लेकिन यह बहुत अधिक हो सकता है यदि आवेदन में कुछ राज्य हैं या इसके राज्य विशेष रूप से गतिशील नहीं हैं।