डिस्पोज़ पैटर्न: Difference between revisions
No edit summary |
No edit summary |
||
(7 intermediate revisions by 4 users not shown) | |||
Line 1: | Line 1: | ||
{{short description|Software design pattern in which resources held by objects can be explicitly released}} | {{short description|Software design pattern in which resources held by objects can be explicitly released}} | ||
[[ऑब्जेक्ट ओरिएंटेड प्रोग्रामिंग]] में, '''डिस्पोज़ पैटर्न''' [[संसाधन प्रबंधन (कंप्यूटिंग)|संसाधन प्रबंधन]] के लिए एक डिज़ाइन पैटर्न होता है। इस पैटर्न में, एक [[सिस्टम संसाधन|प्रणाली संसाधन]] एक [[वस्तु (कंप्यूटिंग)|वस्तु]] द्वारा आयोजित किया जाता है, और एक पारंपरिक [[विधि (कंप्यूटर विज्ञान)|विधि]] को कॉल करके जारी किया जाता है - जिसे सामान्यतः भाषा के आधार पर <code>close</code>, <code>dispose</code>, <code>free</code>, <code>release</code> कहा जाता है - जो किसी भी संसाधन को जारी करता है, जिस पर ऑब्जेक्ट होल्ड होता है। कई [[प्रोग्रामिंग भाषा|प्रोग्रामिंग भाषाएं]] सामान्य परिस्थितियों में निपटान विधि को स्पष्ट रूप से कॉल करने से बचने के लिए [[भाषा निर्माण]] की प्रस्तुत करती है। | |||
[[ऑब्जेक्ट ओरिएंटेड प्रोग्रामिंग]] में, | |||
निपटान पैटर्न मुख्य रूप से उन भाषाओं में उपयोग किया जाता है जिनके रनटाइम पर्यावरण में स्वत: कचरा संग्रह होता है। | निपटान पैटर्न मुख्य रूप से उन भाषाओं में उपयोग किया जाता है जिनके रनटाइम पर्यावरण में स्वत: कचरा संग्रह होता है। | ||
Line 9: | Line 7: | ||
=== संसाधनों को वस्तुओं में लपेटना === | === संसाधनों को वस्तुओं में लपेटना === | ||
ऑब्जेक्ट्स में रैपिंग | ऑब्जेक्ट्स में रैपिंग संसाधन [[Encapsulation (कंप्यूटर प्रोग्रामिंग)|एनकैप्सुलेशन]] का ऑब्जेक्ट-ओरिएंटेड फॉर्म है, और डिस्पोजल पैटर्न को रेखांकित करता है। | ||
संसाधन सामान्यतः [[हैंडल (कंप्यूटिंग)|हैंडल]] (अमूर्त संदर्भ) द्वारा दर्शाए जाते | संसाधन सामान्यतः [[हैंडल (कंप्यूटिंग)|हैंडल]] (अमूर्त संदर्भ) द्वारा दर्शाए जाते है, ठोस रूप से सामान्यतः पूर्णांक होते है, जिनका उपयोग बाहरी प्रणाली के साथ संवाद करने के लिए किया जाता है जो संसाधन प्रदान करता है। उदाहरण के लिए, फ़ाइलें [[ऑपरेटिंग सिस्टम|ऑपरेटिंग प्रणाली]] (विशेष रूप से [[फाइल सिस्टम|फाइल प्रणाली]]) द्वारा प्रदान की जाती है, जो कई प्रणालियों में [[फाइल डिस्क्रिप्टर]] (फ़ाइल का प्रतिनिधित्व करने वाला एक पूर्णांक) के साथ खुली फ़ाइलों का प्रतिनिधित्व करती है। | ||
इन हैंडल का सीधे उपयोग किया जा सकता है, एक चर में मान को संग्रहीत करके और संसाधन का उपयोग करने वाले कार्यों के तर्क के रूप में पारित | इन हैंडल का सीधे उपयोग किया जा सकता है, एक चर में मान को संग्रहीत करके और संसाधन का उपयोग करने वाले कार्यों के तर्क के रूप में पारित करता है । चूंकि, यह अधिकांशतः हैंडल से अमूर्त करने के लिए उपयोगी होता है (उदाहरण के लिए, यदि विभिन्न ऑपरेटिंग प्रणाली अलग-अलग फाइलों का प्रतिनिधित्व करते है), और अतिरिक्त सहायक डेटा को हैंडल के साथ स्टोर करने के लिए, इसलिए हैंडल को [[रिकॉर्ड (कंप्यूटर विज्ञान)|रिकॉर्ड]] में छेत्र के रूप में संग्रहीत किया जा सकता है, यदि यह एक [[अपारदर्शी डेटा प्रकार]] में है, तो यह सूचना छिपाने की सुविधा प्रदान करता है और उपयोगकर्ता को वास्तविक प्रतिनिधित्व से अलग कर दिया जाता है। | ||
उदाहरण के लिए, सी फ़ाइल इनपुट/आउटपुट में, फ़ाइलों को <code>FILE</code> प्रकार की वस्तुओं द्वारा दर्शाया जाता है (भ्रामक रूप से [[फ़ाइल संभाल|फ़ाइल हैंडल]] कहा जाता है: ये एक भाषा-स्तरीय अमूर्तता | उदाहरण के लिए, सी फ़ाइल इनपुट/आउटपुट में, फ़ाइलों को <code>FILE</code> प्रकार की वस्तुओं द्वारा दर्शाया जाता है (भ्रामक रूप से [[फ़ाइल संभाल|फ़ाइल हैंडल]] कहा जाता है: ये एक भाषा-स्तरीय अमूर्तता है), जो फ़ाइल (जैसे कि ऑपरेटिंग प्रणाली) को संभालती है एक फाइल डिस्क्रिप्टर), साथ में सहायक जानकारी जैसे आई/ओ मोड (पढ़ना, लिखना) और धारा में स्थिति आदि। इन वस्तुओं को कॉल करके बनाया जाता है <code>[[C file input/output#fopen|fopen]]</code> (ऑब्जेक्ट-ओरिएंटेड शब्दों में, एक कंस्ट्रक्टर), जो संसाधन प्राप्त करता है और इसके लिए एक सूचक देता है, <code>FILE</code> ऑब्जेक्ट के सूचक पर <code>[[C file input/output#fclose|fclose]]</code> को कॉल करके संसाधन जारी किया जाता है।<ref>{{man|bd|stdio.h|SUS}}</ref> कोड में: | ||
<syntaxhighlight lang="c"> | |||
FILE *f = fopen(filename, mode); | |||
// Do something with f. | |||
fclose(f); | |||
</syntaxhighlight>; | |||
ध्यान दें कि <code>fclose</code> एक <code>FILE *</code> पैरामीटर वाला फ़ंक्शन है। ऑब्जेक्ट-ओरिएंटेड प्रोग्रामिंग में, यह फ़ाइल ऑब्जेक्ट पर एक इंस्टेंस विधि है, जैसा कि पायथन में है: | |||
<syntaxhighlight lang="python"> | |||
f = open(filename) | |||
# Do something with f. | |||
f.close() | |||
</syntaxhighlight> | |||
यह बिल्कुल निपटान पैटर्न है, और पारंपरिक फ़ाइल खोलने और बंद करने से सिंटैक्स और कोड संरचना{{efn|In [[class-based programming]], methods are defined in a class, using an implicit <code>this</code> or <code>self</code> parameter, rather than as functions taking an explicit parameter.}} में अलग है। अन्य संसाधनों को ठीक उसी तरह प्रबंधित किया जा सकता है: एक निर्माता या कारखाने में अधिग्रहित किया जाता है, और एक स्पष्ट <code>close</code> या <code>dispose</code> विधि द्वारा जारी किया जाता है। | |||
=== शीघ्र रिलीज === | === शीघ्र रिलीज === | ||
मौलिक समस्या जिसका समाधान संसाधनों को मुक्त करना है, वह यह है कि संसाधन महंगे | मौलिक समस्या जिसका समाधान संसाधनों को मुक्त करना होता है, वह यह है कि संसाधन महंगे है (उदाहरण के लिए, खुली फ़ाइलों की संख्या पर एक सीमा हो सकती है), और इस प्रकार उन्हें तुरंत जारी किया जाना चाहिए। इसके अतिरिक्त, कभी-कभी कुछ अंतिमीकरण कार्य की आवश्यकता होती है, विशेष रूप से आई/ओ के लिए, जैसे कि फ्लशिंग बफ़र्स यह सुनिश्चित करने के लिए कि सभी डेटा वास्तव में लिखे गए है। | ||
यदि कोई संसाधन | यदि कोई संसाधन प्रभावी रूप से असीमित है, और कोई स्पष्ट अंतिमीकरण आवश्यक नहीं है, तो इसे जारी करना महत्वपूर्ण नहीं है, और वास्तव में अल्पकालिक कार्यक्रम अधिकांशतः संसाधनों को स्पष्ट रूप से जारी नहीं करते है: अल्पावधि के कारण, वे संसाधनों को समाप्त करने की संभावना नहीं रखते है , और वे किसी भी अंतिम रूप देने के लिए [[रनटाइम सिस्टम|रनटाइम प्रणाली]] या ऑपरेटिंग प्रणाली पर भरोसा करते है। | ||
चूंकि, सामान्य संसाधनों में प्रबंधित किया जाना चाहिए (विशेष रूप से लंबे समय तक रहने वाले कार्यक्रमों के लिए, कार्यक्रम जो कई संसाधनों का उपयोग करते | चूंकि, सामान्य संसाधनों में प्रबंधित किया जाना चाहिए (विशेष रूप से लंबे समय तक रहने वाले कार्यक्रमों के लिए, कार्यक्रम जो कई संसाधनों का उपयोग करते है, या सुरक्षा के लिए, यह सुनिश्चित करने के लिए कि डेटा लिखा गया है)। स्पष्ट निपटान का मतलब है कि संसाधन को अंतिम रूप देना और जारी करना नियतात्मक और शीघ्र है: <code>dispose</code> विधि तब तक पूरी नहीं होती जब तक कि ये पूरा नहीं हो जाता। | ||
स्पष्ट निपटान की आवश्यकता का एक विकल्प संसाधन प्रबंधन को जीवन भर के लिए बाँधना है: संसाधन [[वस्तु निर्माण]] के दौरान प्राप्त किए जाते | स्पष्ट निपटान की आवश्यकता का एक विकल्प संसाधन प्रबंधन को जीवन भर के लिए बाँधना है: संसाधन [[वस्तु निर्माण]] के दौरान प्राप्त किए जाते है, और [[वस्तु विनाश]] के दौरान जारी किए जाते है। इस दृष्टिकोण को [[संसाधन अधिग्रहण प्रारंभ है|संसाधन अधिग्रहण प्रारंभ]] (आरएआईआई) के रूप में जाना जाता है, और इसका उपयोग नियतात्मक स्मृति प्रबंधन (जैसे सी++) वाली भाषाओं में किया जाता है। इस स्थिति में, ऊपर दिए गए उदाहरण में, संसाधन तब प्राप्त होता है जब फ़ाइल ऑब्जेक्ट बनाया जाता है, और जब वेरिएबल का दायरा होता है <code>f</code> बाहर निकल जाता है, फ़ाइल ऑब्जेक्ट कि <code>f</code> संदर्भित करता है नष्ट हो जाता है, और इसके हिस्से के रूप में, संसाधन जारी किया जाता है। | ||
आरएआईआई निर्धारक होने के कारण वस्तु जीवनकाल पर निर्भर करता है | आरएआईआई निर्धारक होने के कारण वस्तु जीवनकाल पर निर्भर करता है, चूँकि, स्वचालित मेमोरी प्रबंधन के साथ, ऑब्जेक्ट लाइफटाइम प्रोग्रामर की चिंता का विषय नहीं होता है: वस्तुओं को किसी बिंदु पर नष्ट कर दिया जाता है, जब उनका उपयोग नहीं किया जाता है, लेकिन जब अमूर्त होता है। दरअसल, जीवनकाल अधिकांशतः निर्धारक नहीं होता है, चूंकि यह हो सकता है, विशेष रूप से यदि संदर्भ गणना का उपयोग किया जाता है। दरअसल, कुछ स्थितियों में इस बात की कोई गारंटी नहीं है कि वस्तुओं को कभी भी अंतिम रूप दिया जाएगा: जब कार्यक्रम समाप्त हो जाता है, तो यह वस्तुओं को अंतिम रूप नहीं दे सकता है, और इसके अतिरिक्त केवल ऑपरेटिंग प्रणाली को स्मृति को पुनः प्राप्त करने देता है, यदि अंतिम रूप देने की आवश्यकता है (उदाहरण के लिए, बफर फ्लश करने के लिए), डेटा हानि हो सकती है। | ||
इस प्रकार संसाधन प्रबंधन को जीवन भर वस्तु के साथ जोड़कर, निपटान पैटर्न संसाधनों को तुरंत जारी करने की अनुमति देता है, जबकि स्मृति प्रबंधन के लिए कार्यान्वयन लचीलापन प्रदान करता है। इसकी लागत यह है कि संसाधनों को मैन्युअल रूप से प्रबंधित किया | इस प्रकार संसाधन प्रबंधन को जीवन भर वस्तु के साथ जोड़कर, निपटान पैटर्न संसाधनों को तुरंत जारी करने की अनुमति देता है, जबकि स्मृति प्रबंधन के लिए कार्यान्वयन लचीलापन प्रदान करता है। इसकी लागत यह है कि संसाधनों को मैन्युअल रूप से प्रबंधित किया जाता है, जो त्रुटि-प्रवण हो सकता है। | ||
== प्रारंभिक निकास == | == प्रारंभिक निकास == | ||
डिस्पोजल पैटर्न के साथ एक प्रमुख समस्या यह है कि यदि <code>dispose</code> विधि नहीं कहा जाता है, तो संसाधन लीक हो जाता है। इसका एक सामान्य कारण जल्दी वापसी या अपवाद के कारण किसी समारोह से जल्दी बाहर निकलना है। | डिस्पोजल पैटर्न के साथ एक प्रमुख समस्या यह है कि यदि <code>dispose</code> विधि नहीं कहा जाता है, तो संसाधन लीक हो जाता है। इसका एक सामान्य कारण जल्दी वापसी या अपवाद के कारण किसी समारोह से जल्दी बाहर निकलना होता है। | ||
उदाहरण के लिए: | उदाहरण के लिए: | ||
Line 85: | Line 88: | ||
resource.dispose(); | resource.dispose(); | ||
} | } | ||
<code>try...finally</code> निर्माण उचित [[अपवाद सुरक्षा]] के लिए आवश्यक है, क्योंकि <code>finally</code> में ब्लॉक क्लीनअप लॉजिक के निष्पादन को सक्षम करता है चाहे कोई अपवाद फेंका गया हो या नहीं <code>try</code> अवरोध उत्पन्न | <code>try...finally</code> निर्माण उचित [[अपवाद सुरक्षा]] के लिए आवश्यक है, क्योंकि <code>finally</code> में ब्लॉक क्लीनअप लॉजिक के निष्पादन को सक्षम करता है चाहे कोई अपवाद फेंका गया हो या नहीं <code>try</code> अवरोध उत्पन्न करता है। | ||
इस दृष्टिकोण का एक नुकसान यह है कि प्रोग्रामर को अंत में ब्लॉक में स्पष्ट रूप से क्लीनअप कोड जोड़ने की आवश्यकता होती है <code>finally</code> अवरोध उत्पन्न | इस दृष्टिकोण का एक नुकसान यह है कि प्रोग्रामर को अंत में ब्लॉक में स्पष्ट रूप से क्लीनअप कोड जोड़ने की आवश्यकता होती है <code>finally</code> अवरोध उत्पन्न होता है। इससे कोड आकार ब्लोट हो जाता है, और ऐसा करने में विफलता कार्यक्रम में संसाधन रिसाव का कारण बनता है। | ||
== भाषा निर्माण == | == भाषा निर्माण == | ||
निपटान पैटर्न के सुरक्षित उपयोग को कम वर्बोज़ बनाने के लिए, कोड के एक ही [[ब्लॉक (प्रोग्रामिंग)|ब्लॉक]] में | निपटान पैटर्न के सुरक्षित उपयोग को कम वर्बोज़ बनाने के लिए, कोड के एक ही [[ब्लॉक (प्रोग्रामिंग)|ब्लॉक]] में रखा जाता है और जारी किए गए संसाधनों के लिए कई भाषाओं में किसी प्रकार का अंतर्निहित समर्थन होता है। | ||
सी शार्प भाषा में <code>using</code> कथन<ref>Microsoft MSDN: [http://msdn.microsoft.com/en-us/library/yh598w02.aspx using Statement (C# Reference)]</ref> है जो स्वचालित रूप से किसी ऑब्जेक्ट पर <code>Dispose</code> विधि को कॉल करता है जो <code>IDisposable</code> [[इंटरफ़ेस (कंप्यूटर विज्ञान)|इंटरफ़ेस]] लागू करता है: | सी शार्प भाषा में <code>using</code> कथन<ref>Microsoft MSDN: [http://msdn.microsoft.com/en-us/library/yh598w02.aspx using Statement (C# Reference)]</ref> है जो स्वचालित रूप से किसी ऑब्जेक्ट पर <code>Dispose</code> विधि को कॉल करता है जो <code>IDisposable</code> [[इंटरफ़ेस (कंप्यूटर विज्ञान)|इंटरफ़ेस]] लागू करता है: | ||
Line 111: | Line 114: | ||
((IDisposable)resource).Dispose(); | ((IDisposable)resource).Dispose(); | ||
} | } | ||
इसी तरह, [[पायथन (प्रोग्रामिंग भाषा)|पायथन]] भाषा में एक <code>with</code> कथन है जिसका उपयोग संदर्भ प्रबंधक वस्तु के साथ समान प्रभाव के लिए किया जा सकता है। कॉन्टेक्स्ट मैनेजर प्रोटोकॉल को <code>__enter__</code> और <code>__exit__</code> विधियों को लागू करने की आवश्यकता होती है, जो कोड के दोहराव को रोकने के लिए स्वचालित रूप से स्टेटमेंट निर्माण द्वारा बुलाए जाते | इसी तरह, [[पायथन (प्रोग्रामिंग भाषा)|पायथन]] भाषा में एक <code>with</code> कथन है जिसका उपयोग संदर्भ प्रबंधक वस्तु के साथ समान प्रभाव के लिए किया जा सकता है। कॉन्टेक्स्ट मैनेजर प्रोटोकॉल को <code>__enter__</code> और <code>__exit__</code> विधियों को लागू करने की आवश्यकता होती है, जो कोड के दोहराव को रोकने के लिए स्वचालित रूप से स्टेटमेंट निर्माण द्वारा बुलाए जाते है, जो अन्यथा <code>try</code>/<code>finally</code> पैटर्न के साथ होते है।<ref>{{cite web |author=[[Guido van Rossum]], Nick Coghlan |date=13 June 2011 |title=PEP 343: The "with" Statement |publisher=Python Software Foundation |url=http://legacy.python.org/dev/peps/pep-0343/ }}</ref> | ||
with resource_context_manager() as resource: | with resource_context_manager() as resource: | ||
# Perform actions with the resource. | # Perform actions with the resource. | ||
Line 117: | Line 120: | ||
# Perform other actions where the resource is guaranteed to be deallocated. | # Perform other actions where the resource is guaranteed to be deallocated. | ||
... | ... | ||
[[जावा (प्रोग्रामिंग भाषा)|जावा]] भाषा ने जावा संस्करण 7 में एक नया सिंटैक्स प्रस्तुत किया जिसे <code>try</code>-साथ-संसाधन कहा जाता है।<ref>Oracle Java tutorial: [http://docs.oracle.com/javase/tutorial/essential/exceptions/tryResourceClose.html The try-with-resources Statement]</ref> इसका उपयोग उन वस्तुओं पर किया जा सकता है जो ऑटोक्लोसेजबल इंटरफ़ेस को लागू करते | [[जावा (प्रोग्रामिंग भाषा)|जावा]] भाषा ने जावा संस्करण 7 में एक नया सिंटैक्स प्रस्तुत किया जिसे <code>try</code>-साथ-संसाधन कहा जाता है।<ref>Oracle Java tutorial: [http://docs.oracle.com/javase/tutorial/essential/exceptions/tryResourceClose.html The try-with-resources Statement]</ref> इसका उपयोग उन वस्तुओं पर किया जा सकता है जो ऑटोक्लोसेजबल इंटरफ़ेस को लागू करते है (जो कि विधि को परिभाषित करता है ()): | ||
try (OutputStream x = new OutputStream(...)) { | try (OutputStream x = new OutputStream(...)) { | ||
// Do something with x | // Do something with x | ||
Line 126: | Line 129: | ||
} // try | } // try | ||
== समस्याएं == | == समस्याएं == | ||
रिटर्न और अपवादों की उपस्थिति में सही संसाधन प्रबंधन की प्रमुख समस्या से परे, और हीप-आधारित संसाधन प्रबंधन (वस्तुओं को जहां वे बनाए गए | रिटर्न और अपवादों की उपस्थिति में सही संसाधन प्रबंधन की प्रमुख समस्या से परे, और हीप-आधारित संसाधन प्रबंधन (वस्तुओं को जहां वे बनाए गए है, वहां से एक अलग दायरे में निपटाना), निपटान पैटर्न से जुड़ी कई और जटिलताएं होती है। इन समस्याओं को [[RAII|आरएआईआई]] द्वारा अधिक हद तक टाला जाता है। चूँकि, सामान्य सरल उपयोग में ये जटिलताएँ उत्पन्न नहीं होती है: एक संसाधन प्राप्त करता है, इसके साथ कुछ करता है, इसे स्वचालित रूप से जारी करता है। | ||
एक मौलिक समस्या यह है कि एक संसाधन का होना अब एक [[वर्ग अपरिवर्तनीय]] नहीं है (संसाधन वस्तु निर्माण | एक मौलिक समस्या यह है कि एक संसाधन का होना अब एक [[वर्ग अपरिवर्तनीय]] नहीं है (संसाधन वस्तु निर्माण तब तक रखा जाता है जब तक इसका निपटान नहीं किया जाता है, लेकिन वस्तु अभी भी इस बिंदु पर जीवित है), इसलिए संसाधन उपलब्ध नहीं हो सकता है जब वस्तु कोशिश करती है इसका उपयोग करें, उदाहरण के लिए बंद फ़ाइल से पढ़ने की कोशिश कर रहा है। इसका मतलब यह है कि संसाधन का उपयोग करने वाली वस्तु पर सभी विधियां संभावित रूप से असफल हो जाती है, सामान्यतः एक त्रुटि वापस करता है या अपवाद उठता है। व्यवहार में यह मामूली है, क्योंकि संसाधनों का उपयोग सामान्यतः अन्य कारणों से भी विफल हो सकता है (उदाहरण के लिए, किसी फ़ाइल के अंत को पढ़ने की कोशिश करना), इसलिए ये विधियाँ पहले से ही विफल हो सकती है, और संसाधन न होने से बस एक और संभावित विफलता जुड़ जाती है। इसे लागू करने का एक मानक विधि ऑब्जेक्ट में एक बूलियन छेत्र जोड़ना होता है, जिसे <code>disposed</code> कहा जाता है, जिसे <code>dispose</code> करके सही पर सेट किया जाता है, और एक [[गार्ड क्लॉज]] द्वारा सभी विधियों (जो संसाधन का उपयोग करते है) के लिए चेक किया जाता है, एक अपवाद उठाते हुए (जैसे कि <code>ObjectDisposedException</code> .NET में) यदि वस्तु का निपटान किया गया होता है।<ref name="msdn_dispose">{{cite web |url=https://msdn.microsoft.com/en-us/library/b1yfkh5e(v=vs.110).aspx |title=निपटान पैटर्न}}</रेफरी> | ||
इसके अलावा, कॉल करना संभव है <code>dispose</code> किसी वस्तु पर एक से अधिक बार हालांकि यह एक प्रोग्रामिंग त्रुटि का संकेत दे सकता है (संसाधन धारण करने वाली प्रत्येक वस्तु को एक बार ठीक से निपटाया जाना चाहिए), यह सरल, अधिक मजबूत है, और इस प्रकार आमतौर पर इसके लिए बेहतर है <code>dispose</code> बेवकूफ होना (मतलब कई बार कॉल करना एक बार कॉल करने के समान है)।यह उसी बूलियन का उपयोग करके आसानी से कार्यान्वित किया जाता है <code>disposed</code> फ़ील्ड और शुरुआत में गार्ड क्लॉज में इसकी जाँच करना <code>dispose</code>, उस मामले में अपवाद उठाने के बजाय तत्काल लौट रहा है।जावा डिस्पोजेबल प्रकारों को अलग करता है (वे जो [https://docs.oracle.com/javase/8/docs/api/java/lang/AutoCloseable.html AutoCloseable] लागू करते हैं) डिस्पोजेबल प्रकारों से अलग होते हैं जहां निपटान बेवकूफ है (उप प्रकार [https: //docs.oracle.com/javase/8/docs/api/java/io/Closeable.html Closeable])। | इसके अलावा, कॉल करना संभव है <code>dispose</code> किसी वस्तु पर एक से अधिक बार हालांकि यह एक प्रोग्रामिंग त्रुटि का संकेत दे सकता है (संसाधन धारण करने वाली प्रत्येक वस्तु को एक बार ठीक से निपटाया जाना चाहिए), यह सरल, अधिक मजबूत है, और इस प्रकार आमतौर पर इसके लिए बेहतर है <code>dispose</code> बेवकूफ होना (मतलब कई बार कॉल करना एक बार कॉल करने के समान है)।यह उसी बूलियन का उपयोग करके आसानी से कार्यान्वित किया जाता है <code>disposed</code> फ़ील्ड और शुरुआत में गार्ड क्लॉज में इसकी जाँच करना <code>dispose</code>, उस मामले में अपवाद उठाने के बजाय तत्काल लौट रहा है।जावा डिस्पोजेबल प्रकारों को अलग करता है (वे जो [https://docs.oracle.com/javase/8/docs/api/java/lang/AutoCloseable.html AutoCloseable] लागू करते हैं) डिस्पोजेबल प्रकारों से अलग होते हैं जहां निपटान बेवकूफ है (उप प्रकार [https: //docs.oracle.com/javase/8/docs/api/java/io/Closeable.html Closeable])। | ||
Line 150: | Line 153: | ||
==अग्रिम पठन== | ==अग्रिम पठन== | ||
* Microsoft Developer Network: [https://msdn.microsoft.com/en-us/library/b1yfkh5e(v=vs.110).aspx Dispose Pattern] | * Microsoft Developer Network: [https://msdn.microsoft.com/en-us/library/b1yfkh5e(v=vs.110).aspx Dispose Pattern] | ||
[[Category:Created On 19/02/2023]] | [[Category:Created On 19/02/2023]] | ||
[[Category:Lua-based templates]] | |||
[[Category:Machine Translated Page]] | |||
[[Category:Pages with script errors]] | |||
[[Category:Short description with empty Wikidata description]] | |||
[[Category:Template documentation pages|Short description/doc]] | |||
[[Category:Templates Vigyan Ready]] | |||
[[Category:Templates that add a tracking category]] | |||
[[Category:Templates that generate short descriptions]] | |||
[[Category:Templates using TemplateData]] | |||
[[Category:ऑब्जेक्ट ओरिएंटेड प्रोग्रामिंग]] | |||
[[Category:सॉफ्टवेयर डिजाइन पैटर्न]] | |||
[[Category:स्मृति प्रबंधन]] |
Latest revision as of 10:41, 15 March 2023
ऑब्जेक्ट ओरिएंटेड प्रोग्रामिंग में, डिस्पोज़ पैटर्न संसाधन प्रबंधन के लिए एक डिज़ाइन पैटर्न होता है। इस पैटर्न में, एक प्रणाली संसाधन एक वस्तु द्वारा आयोजित किया जाता है, और एक पारंपरिक विधि को कॉल करके जारी किया जाता है - जिसे सामान्यतः भाषा के आधार पर close
, dispose
, free
, release
कहा जाता है - जो किसी भी संसाधन को जारी करता है, जिस पर ऑब्जेक्ट होल्ड होता है। कई प्रोग्रामिंग भाषाएं सामान्य परिस्थितियों में निपटान विधि को स्पष्ट रूप से कॉल करने से बचने के लिए भाषा निर्माण की प्रस्तुत करती है।
निपटान पैटर्न मुख्य रूप से उन भाषाओं में उपयोग किया जाता है जिनके रनटाइम पर्यावरण में स्वत: कचरा संग्रह होता है।
प्रेरणा
संसाधनों को वस्तुओं में लपेटना
ऑब्जेक्ट्स में रैपिंग संसाधन एनकैप्सुलेशन का ऑब्जेक्ट-ओरिएंटेड फॉर्म है, और डिस्पोजल पैटर्न को रेखांकित करता है।
संसाधन सामान्यतः हैंडल (अमूर्त संदर्भ) द्वारा दर्शाए जाते है, ठोस रूप से सामान्यतः पूर्णांक होते है, जिनका उपयोग बाहरी प्रणाली के साथ संवाद करने के लिए किया जाता है जो संसाधन प्रदान करता है। उदाहरण के लिए, फ़ाइलें ऑपरेटिंग प्रणाली (विशेष रूप से फाइल प्रणाली) द्वारा प्रदान की जाती है, जो कई प्रणालियों में फाइल डिस्क्रिप्टर (फ़ाइल का प्रतिनिधित्व करने वाला एक पूर्णांक) के साथ खुली फ़ाइलों का प्रतिनिधित्व करती है।
इन हैंडल का सीधे उपयोग किया जा सकता है, एक चर में मान को संग्रहीत करके और संसाधन का उपयोग करने वाले कार्यों के तर्क के रूप में पारित करता है । चूंकि, यह अधिकांशतः हैंडल से अमूर्त करने के लिए उपयोगी होता है (उदाहरण के लिए, यदि विभिन्न ऑपरेटिंग प्रणाली अलग-अलग फाइलों का प्रतिनिधित्व करते है), और अतिरिक्त सहायक डेटा को हैंडल के साथ स्टोर करने के लिए, इसलिए हैंडल को रिकॉर्ड में छेत्र के रूप में संग्रहीत किया जा सकता है, यदि यह एक अपारदर्शी डेटा प्रकार में है, तो यह सूचना छिपाने की सुविधा प्रदान करता है और उपयोगकर्ता को वास्तविक प्रतिनिधित्व से अलग कर दिया जाता है।
उदाहरण के लिए, सी फ़ाइल इनपुट/आउटपुट में, फ़ाइलों को FILE
प्रकार की वस्तुओं द्वारा दर्शाया जाता है (भ्रामक रूप से फ़ाइल हैंडल कहा जाता है: ये एक भाषा-स्तरीय अमूर्तता है), जो फ़ाइल (जैसे कि ऑपरेटिंग प्रणाली) को संभालती है एक फाइल डिस्क्रिप्टर), साथ में सहायक जानकारी जैसे आई/ओ मोड (पढ़ना, लिखना) और धारा में स्थिति आदि। इन वस्तुओं को कॉल करके बनाया जाता है fopen
(ऑब्जेक्ट-ओरिएंटेड शब्दों में, एक कंस्ट्रक्टर), जो संसाधन प्राप्त करता है और इसके लिए एक सूचक देता है, FILE
ऑब्जेक्ट के सूचक पर fclose
को कॉल करके संसाधन जारी किया जाता है।[1] कोड में:
FILE *f = fopen(filename, mode);
// Do something with f.
fclose(f);
;
ध्यान दें कि fclose
एक FILE *
पैरामीटर वाला फ़ंक्शन है। ऑब्जेक्ट-ओरिएंटेड प्रोग्रामिंग में, यह फ़ाइल ऑब्जेक्ट पर एक इंस्टेंस विधि है, जैसा कि पायथन में है:
f = open(filename)
# Do something with f.
f.close()
यह बिल्कुल निपटान पैटर्न है, और पारंपरिक फ़ाइल खोलने और बंद करने से सिंटैक्स और कोड संरचना[lower-alpha 1] में अलग है। अन्य संसाधनों को ठीक उसी तरह प्रबंधित किया जा सकता है: एक निर्माता या कारखाने में अधिग्रहित किया जाता है, और एक स्पष्ट close
या dispose
विधि द्वारा जारी किया जाता है।
शीघ्र रिलीज
मौलिक समस्या जिसका समाधान संसाधनों को मुक्त करना होता है, वह यह है कि संसाधन महंगे है (उदाहरण के लिए, खुली फ़ाइलों की संख्या पर एक सीमा हो सकती है), और इस प्रकार उन्हें तुरंत जारी किया जाना चाहिए। इसके अतिरिक्त, कभी-कभी कुछ अंतिमीकरण कार्य की आवश्यकता होती है, विशेष रूप से आई/ओ के लिए, जैसे कि फ्लशिंग बफ़र्स यह सुनिश्चित करने के लिए कि सभी डेटा वास्तव में लिखे गए है।
यदि कोई संसाधन प्रभावी रूप से असीमित है, और कोई स्पष्ट अंतिमीकरण आवश्यक नहीं है, तो इसे जारी करना महत्वपूर्ण नहीं है, और वास्तव में अल्पकालिक कार्यक्रम अधिकांशतः संसाधनों को स्पष्ट रूप से जारी नहीं करते है: अल्पावधि के कारण, वे संसाधनों को समाप्त करने की संभावना नहीं रखते है , और वे किसी भी अंतिम रूप देने के लिए रनटाइम प्रणाली या ऑपरेटिंग प्रणाली पर भरोसा करते है।
चूंकि, सामान्य संसाधनों में प्रबंधित किया जाना चाहिए (विशेष रूप से लंबे समय तक रहने वाले कार्यक्रमों के लिए, कार्यक्रम जो कई संसाधनों का उपयोग करते है, या सुरक्षा के लिए, यह सुनिश्चित करने के लिए कि डेटा लिखा गया है)। स्पष्ट निपटान का मतलब है कि संसाधन को अंतिम रूप देना और जारी करना नियतात्मक और शीघ्र है: dispose
विधि तब तक पूरी नहीं होती जब तक कि ये पूरा नहीं हो जाता।
स्पष्ट निपटान की आवश्यकता का एक विकल्प संसाधन प्रबंधन को जीवन भर के लिए बाँधना है: संसाधन वस्तु निर्माण के दौरान प्राप्त किए जाते है, और वस्तु विनाश के दौरान जारी किए जाते है। इस दृष्टिकोण को संसाधन अधिग्रहण प्रारंभ (आरएआईआई) के रूप में जाना जाता है, और इसका उपयोग नियतात्मक स्मृति प्रबंधन (जैसे सी++) वाली भाषाओं में किया जाता है। इस स्थिति में, ऊपर दिए गए उदाहरण में, संसाधन तब प्राप्त होता है जब फ़ाइल ऑब्जेक्ट बनाया जाता है, और जब वेरिएबल का दायरा होता है f
बाहर निकल जाता है, फ़ाइल ऑब्जेक्ट कि f
संदर्भित करता है नष्ट हो जाता है, और इसके हिस्से के रूप में, संसाधन जारी किया जाता है।
आरएआईआई निर्धारक होने के कारण वस्तु जीवनकाल पर निर्भर करता है, चूँकि, स्वचालित मेमोरी प्रबंधन के साथ, ऑब्जेक्ट लाइफटाइम प्रोग्रामर की चिंता का विषय नहीं होता है: वस्तुओं को किसी बिंदु पर नष्ट कर दिया जाता है, जब उनका उपयोग नहीं किया जाता है, लेकिन जब अमूर्त होता है। दरअसल, जीवनकाल अधिकांशतः निर्धारक नहीं होता है, चूंकि यह हो सकता है, विशेष रूप से यदि संदर्भ गणना का उपयोग किया जाता है। दरअसल, कुछ स्थितियों में इस बात की कोई गारंटी नहीं है कि वस्तुओं को कभी भी अंतिम रूप दिया जाएगा: जब कार्यक्रम समाप्त हो जाता है, तो यह वस्तुओं को अंतिम रूप नहीं दे सकता है, और इसके अतिरिक्त केवल ऑपरेटिंग प्रणाली को स्मृति को पुनः प्राप्त करने देता है, यदि अंतिम रूप देने की आवश्यकता है (उदाहरण के लिए, बफर फ्लश करने के लिए), डेटा हानि हो सकती है।
इस प्रकार संसाधन प्रबंधन को जीवन भर वस्तु के साथ जोड़कर, निपटान पैटर्न संसाधनों को तुरंत जारी करने की अनुमति देता है, जबकि स्मृति प्रबंधन के लिए कार्यान्वयन लचीलापन प्रदान करता है। इसकी लागत यह है कि संसाधनों को मैन्युअल रूप से प्रबंधित किया जाता है, जो त्रुटि-प्रवण हो सकता है।
प्रारंभिक निकास
डिस्पोजल पैटर्न के साथ एक प्रमुख समस्या यह है कि यदि dispose
विधि नहीं कहा जाता है, तो संसाधन लीक हो जाता है। इसका एक सामान्य कारण जल्दी वापसी या अपवाद के कारण किसी समारोह से जल्दी बाहर निकलना होता है।
उदाहरण के लिए:
def func(filename): f = open(filename) if a: return x f.close() return y
यदि फ़ंक्शन पहली वापसी पर लौटता है, तो फ़ाइल कभी बंद नहीं होती है और संसाधन लीक हो जाता है।
def func(filename): f = open(filename) g(f) # Do something with f that may raise an exception. f.close()
यदि हस्तक्षेप करने वाला कोड अपवाद उठाता है, तो फ़ंक्शन जल्दी निकल जाता है और फ़ाइल कभी बंद नहीं होती है, इसलिए संसाधन लीक हो जाता है।
इन दोनों को try...finally
निर्माण द्वारा नियंत्रित किया जा सकता है, जो यह सुनिश्चित करता है कि अंत में खंड हमेशा बाहर निकलने पर निष्पादित किया जाता है:
def func(filename): try: f = open(filename) # Do something. finally: f.close()
अधिक सामान्य रूप से:
Resource resource = getResource(); try { // Resource has been acquired; perform actions with the resource. ... } finally { // Release resource, even if an exception was thrown. resource.dispose(); }
try...finally
निर्माण उचित अपवाद सुरक्षा के लिए आवश्यक है, क्योंकि finally
में ब्लॉक क्लीनअप लॉजिक के निष्पादन को सक्षम करता है चाहे कोई अपवाद फेंका गया हो या नहीं try
अवरोध उत्पन्न करता है।
इस दृष्टिकोण का एक नुकसान यह है कि प्रोग्रामर को अंत में ब्लॉक में स्पष्ट रूप से क्लीनअप कोड जोड़ने की आवश्यकता होती है finally
अवरोध उत्पन्न होता है। इससे कोड आकार ब्लोट हो जाता है, और ऐसा करने में विफलता कार्यक्रम में संसाधन रिसाव का कारण बनता है।
भाषा निर्माण
निपटान पैटर्न के सुरक्षित उपयोग को कम वर्बोज़ बनाने के लिए, कोड के एक ही ब्लॉक में रखा जाता है और जारी किए गए संसाधनों के लिए कई भाषाओं में किसी प्रकार का अंतर्निहित समर्थन होता है।
सी शार्प भाषा में using
कथन[2] है जो स्वचालित रूप से किसी ऑब्जेक्ट पर Dispose
विधि को कॉल करता है जो IDisposable
इंटरफ़ेस लागू करता है:
using (Resource resource = GetResource()) { // Perform actions with the resource. ... }
जो इसके बराबर है:
Resource resource = GetResource() try { // Perform actions with the resource. ... } finally { // Resource might not been acquired, or already freed if (resource != null) ((IDisposable)resource).Dispose(); }
इसी तरह, पायथन भाषा में एक with
कथन है जिसका उपयोग संदर्भ प्रबंधक वस्तु के साथ समान प्रभाव के लिए किया जा सकता है। कॉन्टेक्स्ट मैनेजर प्रोटोकॉल को __enter__
और __exit__
विधियों को लागू करने की आवश्यकता होती है, जो कोड के दोहराव को रोकने के लिए स्वचालित रूप से स्टेटमेंट निर्माण द्वारा बुलाए जाते है, जो अन्यथा try
/finally
पैटर्न के साथ होते है।[3]
with resource_context_manager() as resource: # Perform actions with the resource. ... # Perform other actions where the resource is guaranteed to be deallocated. ...
जावा भाषा ने जावा संस्करण 7 में एक नया सिंटैक्स प्रस्तुत किया जिसे try
-साथ-संसाधन कहा जाता है।[4] इसका उपयोग उन वस्तुओं पर किया जा सकता है जो ऑटोक्लोसेजबल इंटरफ़ेस को लागू करते है (जो कि विधि को परिभाषित करता है ()):
try (OutputStream x = new OutputStream(...)) { // Do something with x } catch (IOException ex) { // Handle exception // The resource x is automatically closed } // try
समस्याएं
रिटर्न और अपवादों की उपस्थिति में सही संसाधन प्रबंधन की प्रमुख समस्या से परे, और हीप-आधारित संसाधन प्रबंधन (वस्तुओं को जहां वे बनाए गए है, वहां से एक अलग दायरे में निपटाना), निपटान पैटर्न से जुड़ी कई और जटिलताएं होती है। इन समस्याओं को आरएआईआई द्वारा अधिक हद तक टाला जाता है। चूँकि, सामान्य सरल उपयोग में ये जटिलताएँ उत्पन्न नहीं होती है: एक संसाधन प्राप्त करता है, इसके साथ कुछ करता है, इसे स्वचालित रूप से जारी करता है।
एक मौलिक समस्या यह है कि एक संसाधन का होना अब एक वर्ग अपरिवर्तनीय नहीं है (संसाधन वस्तु निर्माण तब तक रखा जाता है जब तक इसका निपटान नहीं किया जाता है, लेकिन वस्तु अभी भी इस बिंदु पर जीवित है), इसलिए संसाधन उपलब्ध नहीं हो सकता है जब वस्तु कोशिश करती है इसका उपयोग करें, उदाहरण के लिए बंद फ़ाइल से पढ़ने की कोशिश कर रहा है। इसका मतलब यह है कि संसाधन का उपयोग करने वाली वस्तु पर सभी विधियां संभावित रूप से असफल हो जाती है, सामान्यतः एक त्रुटि वापस करता है या अपवाद उठता है। व्यवहार में यह मामूली है, क्योंकि संसाधनों का उपयोग सामान्यतः अन्य कारणों से भी विफल हो सकता है (उदाहरण के लिए, किसी फ़ाइल के अंत को पढ़ने की कोशिश करना), इसलिए ये विधियाँ पहले से ही विफल हो सकती है, और संसाधन न होने से बस एक और संभावित विफलता जुड़ जाती है। इसे लागू करने का एक मानक विधि ऑब्जेक्ट में एक बूलियन छेत्र जोड़ना होता है, जिसे disposed
कहा जाता है, जिसे dispose
करके सही पर सेट किया जाता है, और एक गार्ड क्लॉज द्वारा सभी विधियों (जो संसाधन का उपयोग करते है) के लिए चेक किया जाता है, एक अपवाद उठाते हुए (जैसे कि ObjectDisposedException
.NET में) यदि वस्तु का निपटान किया गया होता है।[5]
यह भी देखें
- ऑब्जेक्ट लाइफटाइम
- संसाधन अधिग्रहण प्रारंभ है (आरएआईआई)
टिप्पणियाँ
- ↑ In class-based programming, methods are defined in a class, using an implicit
this
orself
parameter, rather than as functions taking an explicit parameter.
संदर्भ
- ↑ The Single UNIX Specification, Version 4 from The Open Group – Base Definitions Reference,
- ↑ Microsoft MSDN: using Statement (C# Reference)
- ↑ Guido van Rossum, Nick Coghlan (13 June 2011). "PEP 343: The "with" Statement". Python Software Foundation.
- ↑ Oracle Java tutorial: The try-with-resources Statement
- ↑ "निपटान पैटर्न".</रेफरी>
इसके अलावा, कॉल करना संभव है
dispose
किसी वस्तु पर एक से अधिक बार हालांकि यह एक प्रोग्रामिंग त्रुटि का संकेत दे सकता है (संसाधन धारण करने वाली प्रत्येक वस्तु को एक बार ठीक से निपटाया जाना चाहिए), यह सरल, अधिक मजबूत है, और इस प्रकार आमतौर पर इसके लिए बेहतर हैdispose
बेवकूफ होना (मतलब कई बार कॉल करना एक बार कॉल करने के समान है)।यह उसी बूलियन का उपयोग करके आसानी से कार्यान्वित किया जाता हैdisposed
फ़ील्ड और शुरुआत में गार्ड क्लॉज में इसकी जाँच करनाdispose
, उस मामले में अपवाद उठाने के बजाय तत्काल लौट रहा है।जावा डिस्पोजेबल प्रकारों को अलग करता है (वे जो AutoCloseable लागू करते हैं) डिस्पोजेबल प्रकारों से अलग होते हैं जहां निपटान बेवकूफ है (उप प्रकार [https: //docs.oracle.com/javase/8/docs/api/java/io/Closeable.html Closeable])। संसाधनों को धारण करने वाली वस्तुओं की विरासत और संरचना की उपस्थिति में विनाश/अंतिमकरण (विनाशकों या अंतिमकर्ताओं के माध्यम से) के समान समस्याएं हैं। इसके अलावा, चूंकि डिस्पोजल पैटर्न में आमतौर पर इसके लिए भाषा समर्थन नहीं होता है, बॉयलरप्लेट कोड आवश्यक है। सबसे पहले, यदि कोई व्युत्पन्न वर्ग a को ओवरराइड करता हैdispose
बेस क्लास में विधि, व्युत्पन्न वर्ग में ओवरराइडिंग विधि को आम तौर पर कॉल करने की आवश्यकता होती हैdispose
आधार वर्ग में विधि, आधार में रखे संसाधनों को ठीक से जारी करने के लिए। दूसरे, यदि किसी वस्तु का किसी अन्य वस्तु के साथ संबंध है जो एक संसाधन रखती है (अर्थात, यदि कोई वस्तु अप्रत्यक्ष रूप से किसी अन्य वस्तु के माध्यम से संसाधन का उपयोग करती है जो सीधे संसाधन का उपयोग करती है), तो क्या अप्रत्यक्ष रूप से उपयोग करने वाली वस्तु डिस्पोजेबल होनी चाहिए? यह इस बात से मेल खाता है कि क्या संबंध मालिक है (ऑब्जेक्ट रचना) या देख रहा है (वस्तु एकत्रीकरण), या यहां तक कि सिर्फ संचार (एसोसिएशन (ऑब्जेक्ट-ओरिएंटेड प्रोग्रामिंग)), और दोनों कन्वेंशन पाए जाते हैं (अप्रत्यक्ष उपयोगकर्ता संसाधन के लिए जिम्मेदार है या जिम्मेदार नहीं है) ). यदि अप्रत्यक्ष उपयोग संसाधन के लिए ज़िम्मेदार है, तो इसे डिस्पोजेबल होना चाहिए, और स्वामित्व वाली वस्तुओं को निपटाने पर निपटाना चाहिए (स्वामित्व वाली वस्तुओं को नष्ट करने या अंतिम रूप देने के समान)। रचना (स्वामित्व) एनकैप्सुलेशन (कंप्यूटर प्रोग्रामिंग) प्रदान करता है (केवल उपयोग की जाने वाली वस्तु को ट्रैक करने की आवश्यकता होती है), लेकिन काफी जटिलता की कीमत पर जब वस्तुओं के बीच आगे संबंध होते हैं, जबकि एकत्रीकरण (देखना) लागत पर काफी सरल होता है एनकैप्सुलेशन की कमी। .NET Framework|.NET में, सम्मेलन केवल संसाधनों के प्रत्यक्ष उपयोगकर्ता के लिए ज़िम्मेदार है: आपको IDisposable केवल तभी लागू करना चाहिए जब आपका प्रकार सीधे अप्रबंधित संसाधनों का उपयोग करता हो।<ref name="idisposable">"IDisposable Interface". Retrieved 2016-04-03.
अग्रिम पठन
- Microsoft Developer Network: Dispose Pattern