2015-06-08 8 views
14

ऐसा लगता है कि आपको कभी भी शून्य नहीं करना चाहिए और इसके बजाय हमेशा नल ऑब्जेक्ट पैटर्न का उपयोग करना चाहिए। संग्रह/मानचित्र/सरणी या बुलायन कार्यों जैसे कि प्रमाणीकृत(), which is shown here का उपयोग करते समय मैं एनओपी की उपयोगीता देख सकता हूं।नल ऑब्जेक्ट पैटर्न

मुझे इस पर कुछ भी नहीं मिला है जो पूरी तरह से आश्वस्त है। मेरे विचारों को व्यवस्थित करने की कोशिश करते हुए यहां मेरे साथ भालू।

मेरी समझ यह है कि एक शून्य वस्तु को वापस करने के बजाय, आप एक वैध वस्तु वापस कर देते हैं जिसे "शून्य" किया गया है।

Car car = getCar(); 

एनओपी का उपयोग नहीं यदि आप अगर वस्तु getCar (से लौटे जाँच करने की आवश्यकता होगी) किसी भी तरीकों कॉल करने से पहले रिक्त है:

उदाहरण के लिए, ग्राहक एक फोन एक वस्तु प्राप्त करने के लिए होगा इस पर:

if (car != null){ 
    color = car.getColor(); 
    doScreenStuff(color); 
    } 

एनओपी का उपयोग करना, बजाय getCar() अशक्त लौटने, यह अब एक वस्तु है कि प्रभावी ढंग से किया गया है देता है "बाहर ध्यान केंद्रित किया"। तो अब हमें if (car != null) करने की आवश्यकता नहीं है और केवल रंग का अनुरोध कर सकते हैं। इसलिए, मुझे लगता है कि जब हम रंग कहते हैं तो हमारी "शून्य आउट" ऑब्जेक्ट "कोई नहीं" वापस आ जाएगी।

यह कैसे मदद करता है? ऐसा लगता है कि एक खाली वस्तु पर आगे बढ़ना और कॉलिंग विधियों का कारण सिर्फ इतना ही दर्द होता है जितना कि सिर्फ शून्य की जांच करता है। अब, जब सूचना प्रदर्शित करने का समय आता है, तो हमें यह जांचना होगा कि रंग "कोई नहीं" है, कि ऊंचाई 0 नहीं है, या आपके पास जो भी अन्य मूल्य हैं। इसलिए अनिवार्य रूप से, यदि कार शून्य है, तो प्रसंस्करण की शुरुआत में जांच करने की बजाय, आप बाद में जांच लें कि हमारे पास कार वस्तु असली कार या विकल्प है। अर्थात। हम खाली वस्तुओं का एक गुच्छा प्रदर्शित नहीं करना चाहते हैं, इसलिए हमें अपनी सभी खाली वस्तुओं को फ़िल्टर करने के लिए कुछ तरीका चाहिए।

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

स्पष्ट रूप से कुछ ऐसा होना चाहिए जो मैं देख रहा हूं। अग्रिम धन्यवाद।

उत्तर

6

शून्य ऑब्जेक्ट पैटर्न केवल तब समझ में आता है जब शून्य ऑब्जेक्ट के लिए उचित, कार्यात्मक मान होता है। इसका उद्देश्य शून्य के रूप में नहीं है, जैसा आपने वर्णन किया है, लेकिन अभी भी कार्यात्मक डेटा के वास्तविक टुकड़े के साथ शून्यता या खालीपन का प्रतिनिधित्व करके शून्य के विचार को पूरी तरह समाप्त करने के लिए है। उदाहरण के लिए, पेड़ संरचना में छेद का प्राकृतिक मामला, as described in the Wikipedia article

एक शून्य कार समझ में नहीं आता है। इस मामले में, ऐसा लगता है कि getCar() के लिए Optional<Car> वापस करने के लिए अधिक उपयुक्त चीज़ होगी।

0

कम से कम मेरे अनुभव में, नल पॉइंटर ऑब्जेक्ट, इसलिए आप शून्य सूचक अपवादों से बचने के लिए आपको एक केंद्रीय स्थान पर शून्य जांच को सीमित कर देते हैं।

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

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

String result = Optional.ofNullable(someInteger) 
    .map(Integer::valueOf) 
    .map(i -> i + 1) 
    .map(Object::toString) 
    .orElse("number not present"); 

System.out.println(result); 
+0

शून्य ऑब्जेक्ट पैटर्न और वैकल्पिक एक ही उद्देश्य की सेवा नहीं करते हैं। वैकल्पिक यह इंगित करने के लिए प्रयोग किया जाता है कि कोई मान मौजूद हो सकता है या नहीं। शून्य ऑब्जेक्ट पैटर्न बस इस तथ्य को एन्कोड कर रहा है कि वहां 'कुछ भी नहीं' वस्तु हो सकती है जो अभी भी उपयोगी व्यवहार है। – Cubic

+0

क्षमा करें, मैंने खुद को स्पष्ट नहीं किया होगा, मैं कह रहा था कि शून्य जांच का विकल्प विकल्प है, और फिर शून्य ऑब्जेक्ट पैटर्न के लिए "यह शून्य ऑब्जेक्ट पैटर्न के लिए कोई प्रतिस्थापन नहीं है"। मैंने थोड़ी देर में शून्य ऑब्जेक्ट पैटर्न का उपयोग नहीं किया है क्योंकि मेरे पास हालिया उपयोग का मामला नहीं है, लेकिन मैं इसका मतलब यह नहीं बता रहा हूं कि विकल्प नल ऑब्जेक्ट पैटर्न को प्रतिस्थापित करते हैं। –

3

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

जहां तक ​​इस विशेष पैटर्न का संबंध है, यह प्रोग्रामिंग की एक निश्चित शैली मानता है जो आपके लिए अनुचित हो सकता है। मैं इसे कभी भी अपने आप उपयोग नहीं करता क्योंकि मैं वैध मूल्यों (अनुपलब्ध डेटा) के रूप में नल को वापस लौटाता हूं जिन्हें प्रत्येक मामले में अलग-अलग संभाला जाता है, इसलिए "केंद्रीकृत हैंडलिंग" मेरे लिए कोई समझ नहीं लेता है। जब मैं बूलियन लौटाता हूं, तो मैं प्राइमेटिव का उपयोग करता हूं।

नीचे की रेखा यह है कि यदि कोई पैटर्न आपके लिए अप्राकृतिक प्रतीत होता है, तो इसका उपयोग न करें।

+0

मुझे लगता है कि आप सही हैं। प्रोग्रामिंग करते समय मैं गलत पैटर्न का उपयोग करने के बारे में हमेशा चिंतित हूं। इस मामले में, ऐसे लोग प्रतीत होते हैं जो सुझाव देते हैं कि यदि आप नल वापस लौट रहे हैं तो आप पूरी तरह से गलत काम कर रहे हैं: http://www.yegor256.com/2014/05/13/why-null-is-bad.html – TigerBear

6

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

  1. एक "जोड़ना", "योग" या ऐसा ही ऑपरेशन है, जो साहचर्य होने की जरूरत है: a.op(b).op(c) ही है एक monoid एक प्रकार इन बातों के दोनों किया है a.op(b.op(c)) के रूप में।
  2. एक "खाली," "शून्य" या "शून्य" मान, जो ऑपरेशन के तटस्थ तत्व या पहचान तत्व के रूप में कार्य करता है।

शून्य ऑब्जेक्ट पैटर्न का क्लासिक उदाहरण शून्य की बजाय खाली सूची या सरणी वापस करना है। खैर, सूचियां एक monoid हैं, ऑपरेशन और खाली सूची तटस्थ तत्व के रूप में संलग्न के रूप में।

अब, आपके Car उदाहरण में समस्या का सामना करना यह है कि Car वास्तव में एक मोनॉयड नहीं है; "खाली कार" या "तटस्थ कार" की कोई धारणा नहीं है, और वास्तव में एक समझदार ऑपरेशन नहीं है जिसका उपयोग आप दो Car एस को एक साथ जोड़ सकते हैं।

तो आप जिस सिफारिश को सही तरीके से प्राप्त कर रहे हैं वह जावा 8 Optional जैसे कुछ का उपयोग करना है। और चाल कि कोई बात नहीं T है कि किस प्रकार, Optional<T> एक monoid है:

  1. monoid के "गठबंधन" ऑपरेशन "अगर यह empty नहीं है पहले मान लेने, अन्यथा दूसरा मान लेने" है:
    • x || empty = x
    • empty || x = x
  2. तटस्थ तत्व Optional.empty() है, क्योंकि Optional.empty().orElse(anything) सिर्फरूप में ही है।

तो बुनियादी तौर पर, Optional<T> एक आवरण है कि Car तरह प्रकार है कि एक भी नहीं है करने के लिए एक अशक्त वस्तु कहते है। Optional<T>.orElse(T value) विधि जो "पहले गैर- मान" मोनॉयड का थोड़ा सा रिफैक्टर संस्करण है।

0

नूल डिज़ाइन पैटर्न किसी ऑब्जेक्ट के ABSENCE को एक डिफॉल्ट व्यवहार के साथ भरता है और केवल तभी उपयोग किया जाना चाहिए जब एक ऑब्जेक्ट दूसरे के साथ सहयोग करता हो।

नल डिज़ाइन पैटर्न नल अपवाद हैंडलिंग को प्रतिस्थापित करने के लिए नहीं है। यह नल डिजाइन पैटर्न के साइड लाभों में से एक है लेकिन इरादा एक डिफ़ॉल्ट व्यवहार प्रदान करना है।

उदाहरण के लिए नीचे दिए गए नमूना pseduo कोड पर विचार करें। यह एक साधारण ग्राहक वर्ग है जो डिस्काउंट ऑब्जेक्ट पर छूट गणना का प्रतिनिधित्व कर रहा है।

class Customer { 
    IDiscount dis = new NormalDiscount(); 
    public double CalculateDiscount() { 
     return dis.Calculate(); 
    } 
    // Code removed for simplicity 
} 

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

class DefaultedCustomer : Customer { 
    IDiscount dis = null; 
    public double CalculateDiscount() { 
     return dis.Calculate(); <---- This will crash in parent 
    } 
    // Code removed for simplicity 
} 

तो तरीके डेवलपर्स से एक का समाधान इस NULLs के लिए मेरी जाँच और शून्य लौटने है। यदि आप अपनी आंखें बंद करते हैं और तर्कसंगत सोचते हैं तो यह वास्तव में व्यावसायिक परिदृश्य है जहां डिफ़ॉल्ट ग्राहक के लिए कोई छूट नहीं है।

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

public class DefaultDiscount : IDiscount { 
    public void Calculate() { 
     return 0; 
    } 
} 

NULLs की जरूरत है, लेकिन के लिए अपवाद सहयोग से एक वस्तु के अभाव फिक्सिंग के रूप में ऊपर दिखाए गए के लिए नहीं निपटने। यदि कोई सहयोग नहीं है तो नल डिज़ाइन पैटर्न समझ में नहीं आता है।

क्योंकि शून्य डिज़ाइन पैटर्न शून्य चेकों के

बचा पाने लेकिन उस प्रभाव और साइड लाभ के बाद की अधिक नहीं बल्कि मुख्य उद्देश्य है।

सभी उपरोक्त विचार मैंने इस NULL Design pattern in C# से लिया है जो डू और डॉट्स ऑफ़ न्यूल बताता है।

-1

कार पर वैकल्पिक विकल्प कार की वस्तु वास्तव में मौजूद है या नहीं, यह जांचने का चरण नहीं ले जाएगा।

कार लौटने पर, आप जांचेंगे कि क्या (कार! = शून्य) है। इसी प्रकार जब आप वैकल्पिक पहुंचते हैं तो जांच करें कि (car.isPresent()) तो car.get()।

उपस्थिति की जांच किए बिना प्राप्त() प्राप्त करना स्वीकार्य नहीं है और त्रुटियों को फेंकने के लिए चेकस्टाइल कॉन्फ़िगरेशन का उपयोग करके आसानी से पहचाना जा सकता है और इससे बचा जा सकता है।

आप सवाल पूछ सकते हैं .. अगर हम दोनों पैटर्न में इसकी उपस्थिति की जांच कर रहे हैं तो हम इसका क्या फायदा उठा रहे हैं?

उत्तर यह जानने में निहित है कि इसका उपयोग करने से पहले आपको एक चेक करना है।यदि आप वैकल्पिक रूप से वापस लौटने के अभ्यास का सख्ती से पालन करते हैं, जहां कहीं भी यह शून्य हो सकता है, तो आपको नल के लिए जांचने की आवश्यकता नहीं है, यह वैकल्पिक नहीं है।

यह दस्तावेजों के दस्तावेज़ीकरण के एक प्रोग्रामेटिक तरीके के रूप में कार्य करता है जो आंतरिक रूप से चेकस्टाइल के माध्यम से इसकी जांच को लागू करने में मदद करता है।

+0

वैकल्पिक नल ऑब्जेक्ट पैटर्न (https://en.wikipedia.org/wiki/Null_Object_pattern) के समान नहीं है –

+0

केवल 'isPresent() 'और' get() 'के लिए' वैकल्पिक 'का उपयोग करना आपके 20mph में जा रहा है ब्रांड नई लेम्बोर्गिनी। इस स्थिति में करने के लिए बेहतर चीज है 'getCar()। IfPresent (कार -> doScreenStuff (car.getcolor())) ' – Michael

संबंधित मुद्दे