डिस्पोज़ पैटर्न

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

निपटान पैटर्न मुख्य रूप से उन भाषाओं में उपयोग किया जाता है जिनके रनटाइम पर्यावरण में स्वत: कचरा संग्रह होता है (नीचे प्रेरणा देखें)।

संसाधनों को वस्तुओं में लपेटना
ऑब्जेक्ट्स में रैपिंग रिसोर्सेज Encapsulation (कंप्यूटर प्रोग्रामिंग) का ऑब्जेक्ट-ओरिएंटेड रूप है, और डिस्पोजल पैटर्न को रेखांकित करता है।

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

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

उदाहरण के लिए, सी फ़ाइल इनपुट/आउटपुट में, फ़ाइलों को ऑब्जेक्ट द्वारा दर्शाया जाता है  प्रकार (भ्रामक रूप से फ़ाइल संभाल कहा जाता है: ये एक भाषा-स्तर अमूर्त हैं), जो फ़ाइल (जैसे फ़ाइल डिस्क्रिप्टर) में एक (ऑपरेटिंग सिस्टम) हैंडल को स्टोर करता है, साथ में I/O मोड (पढ़ना, लिखना) जैसी सहायक जानकारी के साथ और धारा में स्थिति। ये ऑब्जेक्ट कॉल करके बनाए जाते हैं   (ऑब्जेक्ट-ओरिएंटेड शर्तों में, एक कन्स्ट्रक्टर_ (ऑब्जेक्ट-ओरिएंटेड_प्रोग्रामिंग)), जो संसाधन प्राप्त करता है और इसके लिए एक सूचक देता है; संसाधन कॉल करके जारी किया जाता है   एक संकेतक पर   वस्तु। कोड में:

<वाक्यविन्यास प्रकाश लैंग = सी> फ़ाइल * f = fopen (फ़ाइल नाम, मोड); // f के साथ कुछ करें। एफक्लोज (एफ); 

ध्यान दें कि  एक के साथ एक समारोह है   पैरामीटर। ऑब्जेक्ट-ओरिएंटेड प्रोग्रामिंग में, यह फ़ाइल ऑब्जेक्ट पर एक इंस्टेंस विधि है, जैसा कि पायथन में है:

<वाक्यविन्यास लैंग = अजगर> च = खुला (फ़ाइल नाम) च बंद 
 * 1) f के साथ कुछ करें।

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

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

यदि कोई संसाधन असीमित या प्रभावी रूप से असीमित है, और कोई स्पष्ट अंतिमीकरण आवश्यक नहीं है, तो इसे जारी करना महत्वपूर्ण नहीं है, और वास्तव में अल्पकालिक कार्यक्रम अक्सर संसाधनों को स्पष्ट रूप से जारी नहीं करते हैं: अल्पावधि के कारण, वे संसाधनों को समाप्त करने की संभावना नहीं रखते हैं, और वे किसी भी अंतिम रूप देने के लिए रनटाइम सिस्टम या ऑपरेटिंग सिस्टम पर भरोसा करते हैं।

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

स्पष्ट निपटान की आवश्यकता का एक विकल्प संसाधन प्रबंधन को जीवन भर के लिए बाँधना है: संसाधन वस्तु निर्माण के दौरान प्राप्त किए जाते हैं, और वस्तु विनाश के दौरान जारी किए जाते हैं। इस दृष्टिकोण को संसाधन अधिग्रहण प्रारंभ है (RAII) मुहावरा के रूप में जाना जाता है, और इसका उपयोग नियतात्मक स्मृति प्रबंधन (जैसे C ++) वाली भाषाओं में किया जाता है। इस स्थिति में, ऊपर दिए गए उदाहरण में, संसाधन तब प्राप्त होता है जब फ़ाइल ऑब्जेक्ट बनाया जाता है, और जब वेरिएबल का दायरा होता है  बाहर निकल गया है, फ़ाइल ऑब्जेक्ट कि   संदर्भित करता है नष्ट हो जाता है, और इसके हिस्से के रूप में, संसाधन जारी किया जाता है।

RAII निर्धारक होने के कारण वस्तु जीवनकाल पर निर्भर करता है; हालाँकि, स्वचालित मेमोरी प्रबंधन के साथ, ऑब्जेक्ट लाइफटाइम प्रोग्रामर की चिंता का विषय नहीं है: वस्तुओं को किसी बिंदु पर नष्ट कर दिया जाता है, जब उनका उपयोग नहीं किया जाता है, लेकिन जब अमूर्त होता है। दरअसल, जीवनकाल अक्सर निर्धारक नहीं होता है, हालांकि यह हो सकता है, विशेष रूप से यदि संदर्भ गणना का उपयोग किया जाता है। दरअसल, कुछ मामलों में इस बात की कोई गारंटी नहीं है कि वस्तुओं को कभी भी अंतिम रूप दिया जाएगा: जब कार्यक्रम समाप्त हो जाता है, तो यह वस्तुओं को अंतिम रूप नहीं दे सकता है, और इसके बजाय केवल ऑपरेटिंग सिस्टम को स्मृति को पुनः प्राप्त करने दें; यदि अंतिम रूप देने की आवश्यकता है (उदाहरण के लिए, बफर फ्लश करने के लिए), डेटा हानि हो सकती है।

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

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

उदाहरण के लिए: <वाक्यविन्यास लैंग = अजगर> def func (फ़ाइल नाम): च = खुला (फ़ाइल नाम) यदि एक: वापसी एक्स च बंद वापसी वाई  यदि फ़ंक्शन पहली वापसी पर लौटता है, तो फ़ाइल कभी बंद नहीं होती है और संसाधन लीक हो जाता है।

<वाक्यविन्यास लैंग = अजगर> def func (फ़ाइल नाम): च = खुला (फ़ाइल नाम) g(f) # f के साथ कुछ ऐसा करें जिससे कोई अपवाद उत्पन्न हो। च बंद  यदि हस्तक्षेप करने वाला कोड अपवाद उठाता है, तो फ़ंक्शन जल्दी निकल जाता है और फ़ाइल कभी बंद नहीं होती है, इसलिए संसाधन लीक हो जाता है।

इन दोनों को एक द्वारा नियंत्रित किया जा सकता है  निर्माण, जो यह सुनिश्चित करता है कि अंत में खंड हमेशा बाहर निकलने पर निष्पादित होता है: <वाक्यविन्यास लैंग = अजगर> def func (फ़ाइल नाम): कोशिश करना: च = खुला (फ़ाइल नाम) # कुछ करो। आखिरकार: च बंद 

अधिक सामान्य रूप से: <वाक्यविन्यास प्रकाश लैंग = csharp> संसाधन संसाधन = getResource ; कोशिश { // संसाधन प्राप्त कर लिया गया है; संसाधन के साथ कार्रवाई करें। ... } आखिरकार { // रिलीज संसाधन, भले ही एक अपवाद फेंक दिया गया हो। संसाधन.निपटान ; }   e> उचित अपवाद सुरक्षा के लिए निर्माण आवश्यक है, क्योंकि   ब्लॉक क्लीनअप लॉजिक के निष्पादन को सक्षम करता है, भले ही कोई अपवाद फेंका गया हो या नहीं   अवरोध पैदा करना।

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

भाषा निर्माण
डिस्पोज़ पैटर्न के सुरक्षित उपयोग को कम वर्बोज़ बनाने के लिए, कई भाषाओं में एक ही ब्लॉक (प्रोग्रामिंग) में रखे और जारी किए गए संसाधनों के लिए किसी प्रकार का अंतर्निहित समर्थन होता है।

सी शार्प (प्रोग्रामिंग लैंग्वेज)|सी# लैंग्वेज की विशेषता है  कथन जो स्वचालित रूप से कॉल करता है   किसी वस्तु पर विधि जो लागू करती है   इंटरफ़ेस (कंप्यूटर विज्ञान):

<वाक्यविन्यास प्रकाश लैंग = csharp> (संसाधन संसाधन = GetResource ) का उपयोग करना {   // संसाधन के साथ कार्य करें। ... }  जो इसके बराबर है: <वाक्यविन्यास प्रकाश लैंग = csharp> संसाधन संसाधन = GetResource कोशिश {   // संसाधन के साथ कार्य करें। ... } आखिरकार {   // संसाधन का अधिग्रहण नहीं किया जा सकता है, या पहले ही मुक्त कर दिया गया है अगर (संसाधन! = अशक्त) ((आईडीस्पोजेबल) संसाधन)। निपटान ; } 

इसी प्रकार, पायथन (प्रोग्रामिंग भाषा) भाषा में एक है  बयान जो एक संदर्भ प्रबंधक वस्तु के समान प्रभाव के लिए इस्तेमाल किया जा सकता है। संदर्भ प्रबंधक प्रोटोकॉल को लागू करने की आवश्यकता है   और   विधियां जो स्वचालित रूप से कॉल की जाती हैं   कथन निर्माण, कोड के दोहराव को रोकने के लिए जो अन्यथा घटित होगा  /  नमूना। <वाक्यविन्यास लैंग = अजगर> संसाधन_संदर्भ_प्रबंधक के साथ संसाधन के रूप में: # संसाधन के साथ कार्रवाई करें। ... ... 
 * 1) अन्य क्रियाएं करें जहां संसाधन को आवंटित करने की गारंटी है।

जावा (प्रोग्रामिंग भाषा) लैंग्वेज ने एक नया सिंटैक्स पेश किया जिसे कहा जाता है -साथ-संसाधन जावा संस्करण 7 में। इसका उपयोग उन वस्तुओं पर किया जा सकता है जो AutoCloseable इंटरफ़ेस को लागू करते हैं (जो कि विधि को परिभाषित करता है ): <वाक्यविन्यास प्रकाश लैंग = जावा> प्रयास करें (आउटपुटस्ट्रीम x = नया आउटपुटस्ट्रीम (...)) { // एक्स के साथ कुछ करो } पकड़ (IOException पूर्व) { // हैंडल अपवाद

// संसाधन x स्वतः बंद हो जाता है } // कोशिश 

समस्याएं
रिटर्न और अपवादों की उपस्थिति में सही संसाधन प्रबंधन की प्रमुख समस्या से परे, और हीप-आधारित संसाधन प्रबंधन (वस्तुओं को जहां वे बनाए गए हैं, वहां से एक अलग दायरे में निपटाना), निपटान पैटर्न से जुड़ी कई और जटिलताएं हैं। इन समस्याओं को RAII द्वारा काफी हद तक टाला जाता है। हालाँकि, सामान्य सरल उपयोग में ये जटिलताएँ उत्पन्न नहीं होती हैं: एक संसाधन प्राप्त करें, इसके साथ कुछ करें, इसे स्वचालित रूप से जारी करें।

एक मौलिक समस्या यह है कि एक संसाधन का होना अब एक वर्ग अपरिवर्तनीय नहीं है (संसाधन वस्तु निर्माण से तब तक रखा जाता है जब तक इसका निपटान नहीं किया जाता है, लेकिन वस्तु अभी भी इस बिंदु पर जीवित है), इसलिए संसाधन उपलब्ध नहीं हो सकता है जब वस्तु कोशिश करती है इसका इस्तेमाल करें, उदाहरण के लिए बंद फ़ाइल से पढ़ने की कोशिश कर रहा है। इसका मतलब यह है कि संसाधन का उपयोग करने वाली वस्तु पर सभी विधियां संभावित रूप से असफल हो जाती हैं, आम तौर पर एक त्रुटि वापस करके या अपवाद उठाकर। व्यवहार में यह मामूली है, क्योंकि संसाधनों का उपयोग आमतौर पर अन्य कारणों से भी विफल हो सकता है (उदाहरण के लिए, किसी फ़ाइल के अंत को पढ़ने की कोशिश करना), इसलिए ये विधियाँ पहले से ही विफल हो सकती हैं, और संसाधन न होने से बस एक और संभावित विफलता जुड़ जाती है. इसे लागू करने का एक मानक तरीका ऑब्जेक्ट में एक बूलियन फ़ील्ड जोड़ना है, जिसे कहा जाता है, जो द्वारा सत्य पर सेट किया गया है  , और एक गार्ड क्लॉज द्वारा सभी विधियों (जो संसाधन का उपयोग करते हैं) के लिए जाँच की जाती है, एक अपवाद (जैसे   in .NET) यदि वस्तु का निपटान किया गया है।

इसके अलावा, कॉल करना संभव है  किसी वस्तु पर एक से अधिक बार हालांकि यह एक प्रोग्रामिंग त्रुटि का संकेत दे सकता है (संसाधन धारण करने वाली प्रत्येक वस्तु को एक बार ठीक से निपटाया जाना चाहिए), यह सरल, अधिक मजबूत है, और इस प्रकार आमतौर पर इसके लिए बेहतर है   बेवकूफ होना (मतलब कई बार कॉल करना एक बार कॉल करने के समान है)। यह उसी बूलियन का उपयोग करके आसानी से कार्यान्वित किया जाता है   फ़ील्ड और शुरुआत में गार्ड क्लॉज में इसकी जाँच करना , उस मामले में अपवाद उठाने के बजाय तत्काल लौट रहा है। जावा डिस्पोजेबल प्रकारों को अलग करता है (वे जो AutoCloseable लागू करते हैं) डिस्पोजेबल प्रकारों से अलग होते हैं जहां निपटान बेवकूफ है (उप प्रकार [https: //docs.oracle.com/javase/8/docs/api/java/io/Closeable.html Closeable])।

संसाधनों को धारण करने वाली वस्तुओं की विरासत और संरचना की उपस्थिति में विनाश/अंतिमकरण (विनाशकों या अंतिमकर्ताओं के माध्यम से) के समान समस्याएं हैं। इसके अलावा, चूंकि डिस्पोजल पैटर्न में आमतौर पर इसके लिए भाषा समर्थन नहीं होता है, बॉयलरप्लेट कोड आवश्यक है। सबसे पहले, यदि कोई व्युत्पन्न वर्ग a को ओवरराइड करता है  बेस क्लास में विधि, व्युत्पन्न वर्ग में ओवरराइडिंग विधि को आम तौर पर कॉल करने की आवश्यकता होती है   आधार वर्ग में विधि, आधार में रखे संसाधनों को ठीक से जारी करने के लिए। दूसरे, यदि किसी वस्तु का किसी अन्य वस्तु के साथ संबंध है जो एक संसाधन रखती है (अर्थात, यदि कोई वस्तु अप्रत्यक्ष रूप से किसी अन्य वस्तु के माध्यम से संसाधन का उपयोग करती है जो सीधे संसाधन का उपयोग करती है), तो क्या अप्रत्यक्ष रूप से उपयोग करने वाली वस्तु डिस्पोजेबल होनी चाहिए? यह इस बात से मेल खाता है कि क्या संबंध मालिक है (ऑब्जेक्ट रचना) या देख रहा है (वस्तु एकत्रीकरण), या यहां तक ​​​​कि सिर्फ संचार (एसोसिएशन (ऑब्जेक्ट-ओरिएंटेड प्रोग्रामिंग)), और दोनों कन्वेंशन पाए जाते हैं (अप्रत्यक्ष उपयोगकर्ता संसाधन के लिए जिम्मेदार है या जिम्मेदार नहीं है) ). यदि अप्रत्यक्ष उपयोग संसाधन के लिए ज़िम्मेदार है, तो इसे डिस्पोजेबल होना चाहिए, और स्वामित्व वाली वस्तुओं को निपटाने पर निपटाना चाहिए (स्वामित्व वाली वस्तुओं को नष्ट करने या अंतिम रूप देने के समान)।

रचना (स्वामित्व) एनकैप्सुलेशन (कंप्यूटर प्रोग्रामिंग) प्रदान करता है (केवल उपयोग की जाने वाली वस्तु को ट्रैक करने की आवश्यकता होती है), लेकिन काफी जटिलता की कीमत पर जब वस्तुओं के बीच आगे संबंध होते हैं, जबकि एकत्रीकरण (देखना) लागत पर काफी सरल होता है एनकैप्सुलेशन की कमी। .NET Framework|.NET में, सम्मेलन केवल संसाधनों के प्रत्यक्ष उपयोगकर्ता के लिए ज़िम्मेदार है: आपको IDisposable केवल तभी लागू करना चाहिए जब आपका प्रकार सीधे अप्रबंधित संसाधनों का उपयोग करता हो। विवरण और अन्य उदाहरणों के लिए संसाधन प्रबंधन (कंप्यूटिंग) देखें।

यह भी देखें

 * ऑब्जेक्ट लाइफटाइम
 * संसाधन अधिग्रहण प्रारंभ है (RAII)

अग्रिम पठन

 * Microsoft Developer Network: Dispose Pattern