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

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

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

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

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

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

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

FILE *f = fopen(filename, mode);

// Do something with f.

fclose(f);

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

f = open(filename)


 * 1) Do something with f.

f.close

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

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

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

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

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

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

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

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

उदाहरण के लिए: 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 यदि हस्तक्षेप करने वाला कोड अपवाद उठाता है, तो फ़ंक्शन जल्दी निकल जाता है और फ़ाइल कभी बंद नहीं होती है, इसलिए संसाधन लीक हो जाता है।

इन दोनों को  निर्माण द्वारा नियंत्रित किया जा सकता है, जो यह सुनिश्चित करता है कि अंत में खंड हमेशा बाहर निकलने पर निष्पादित किया जाता है: 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; } निर्माण उचित अपवाद सुरक्षा के लिए आवश्यक है, क्योंकि   में ब्लॉक क्लीनअप लॉजिक के निष्पादन को सक्षम करता है चाहे कोई अपवाद फेंका गया हो या नहीं   अवरोध उत्पन्न करता है।

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

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

सी शार्प भाषा में  कथन है जो स्वचालित रूप से किसी ऑब्जेक्ट पर   विधि को कॉल करता है जो   इंटरफ़ेस लागू करता है: 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 resource_context_manager as resource: # Perform actions with the resource. ... ... जावा भाषा ने जावा संस्करण 7 में एक नया सिंटैक्स प्रस्तुत किया जिसे -साथ-संसाधन कहा जाता है। इसका उपयोग उन वस्तुओं पर किया जा सकता है जो ऑटोक्लोसेजबल इंटरफ़ेस को लागू करते है (जो कि विधि को परिभाषित करता है ): try (OutputStream x = new OutputStream(...)) { // Do something with x } catch (IOException ex) { // Handle exception // The resource x is automatically closed } // try
 * 1) Perform other actions where the resource is guaranteed to be deallocated.

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

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

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

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

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

यह भी देखें

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

अग्रिम पठन

 * Microsoft Developer Network: Dispose Pattern