निम्नलिखित (एंटी) पैटर्न का नाम क्या है? इसके फायदे और नुकसान क्या हैं?


28

पिछले कुछ महीनों में, मैंने निम्नलिखित तकनीक / पैटर्न पर कुछ बार ठोकर खाई। हालाँकि, मुझे कोई विशिष्ट नाम नहीं मिल रहा है, और न ही मैं इसके सभी फायदे और नुकसान के बारे में 100% निश्चित हूं।

पैटर्न निम्नानुसार है:

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

public interface Vehicle {
    public void accelerate();
    public void decelerate();

    public static class Default {
         public static Vehicle getInstance() {
             return new Car(); // or use Spring to retrieve an instance
         }
    }
 }

मेरे लिए, ऐसा लगता है कि सबसे बड़ा फायदा इस तथ्य में निहित है कि एक डेवलपर को केवल इंटरफ़ेस के बारे में जानने की जरूरत है, न कि इसके कार्यान्वयन की, जैसे कि वह जल्दी से एक उदाहरण बनाना चाहता है।

 Vehicle someVehicle = Vehicle.Default.getInstance();
 someVehicle.accelerate();

इसके अलावा, मैंने इस तकनीक को कॉन्फ़िगरेशन के आधार पर गतिशील रूप से उदाहरण प्रदान करने के लिए स्प्रिंग के साथ एक साथ उपयोग किया जा रहा है। इस संबंध में, यह भी दिखता है कि यह संशोधन के साथ मदद कर सकता है।

फिर भी, मैं यह महसूस नहीं कर सकता कि यह इंटरफ़ेस का दुरुपयोग है क्योंकि यह इंटरफ़ेस को इसके कार्यान्वयन के साथ जोड़ देता है। (निर्भरता उलटा सिद्धांत आदि ..) क्या कोई मुझे बता सकता है कि इस तकनीक को कैसे कहा जाता है, साथ ही इसके फायदे और नुकसान?

अद्यतन करें:

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

public interface Vehicle {
      public void accelerate();
      public void decelerate();

      public static class Default {
           public static final Vehicle INSTANCE = getInstance();

           private static Vehicle getInstance() {
                return new Car(); // or use Spring/factory here
           }
      }
 }

 // Which allows to retrieve a singleton instance using...
 Vehicle someVehicle = Vehicle.Default.INSTANCE;

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


कुछ सिंगलटन पैटर्न?
ब्रायन चेन

मुझे लगता है कि आप सही हैं कि इंटरफ़ेस को इसके कार्यान्वयन के बारे में "पता" नहीं होना चाहिए। शायद Vehicle.Defaultएक कारखाने वर्ग के रूप में पैकेज नाम स्थान में ऊपर ले जाया जाना चाहिए, जैसे VehicleFactory
अगस्तुर

7
वैसे,Vehicle.Default.getInstance() != Vehicle.Default.getInstance()
कोनराड मोरावस्की

20
यहां एंटीपार्टन का उपयोग कार-एनालॉग एंटीपैटर्न का उपयोग करने के लिए किया जाता है, जो पशु-एनालॉग एंटीपैटर से संबंधित है। अधिकांश सॉफ्टवेयर में पहिए या पैर नहीं होते हैं।
पीटर बी

@ पीटर: :-)))) आपने मेरा दिन बना दिया!
डॉक्टर ब्राउन

जवाबों:


24

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

इस निर्माण के कारण मुख्य समस्या यह है कि यह Vehicleऔर के बीच चक्रीय निर्भरता को प्रेरित करता है Car। उदाहरण के लिए, वर्तमान रूप में यह Vehicleएक पुस्तकालय में, और Carदूसरे में रखना संभव नहीं होगा । एक अलग फैक्ट्री क्लास का उपयोग करना और Default.getInstanceवहाँ विधि रखने से उस समस्या का समाधान होगा। सिंगलेट्स से संबंधित किसी भी भ्रम को रोकने के लिए उस पद्धति को एक अलग नाम देना भी एक अच्छा विचार हो सकता है। तो परिणाम कुछ इस तरह हो सकता है

VehicleFactory.createDefaultInstance()


आपके उत्तर के लिए धन्यवाद! मैं मानता हूं कि यह विशेष उदाहरण एसआरपी का उल्लंघन है। हालाँकि, मैं अनिश्चित हूं कि क्या यह अभी भी उल्लंघन है अगर कार्यान्वयन गतिशील रूप से पुनर्प्राप्त किया जाता है। उदाहरण के लिए एक कॉन्फ़िगरेशन फ़ाइल उदाहरण के लिए परिभाषित एक विशेष उदाहरण को पुनः प्राप्त करने के लिए स्प्रिंग (या एक समान रूपरेखा) का उपयोग करके ।
२२

1
@ Jérôme: IMHO नाम VehicleFactoryका एक गैर-नेस्टेड वर्ग नेस्टेड निर्माण की तुलना में अधिक पारंपरिक है Vehicle.Default, विशेष रूप से भ्रामक "getInstance" विधि के साथ। हालांकि, वसंत का उपयोग करके चक्रीय निर्भरता को दरकिनार करना संभव है, मैं व्यक्तिगत रूप से सामान्य ज्ञान के कारण पहले संस्करण को पसंद करूंगा। और, अभी भी यह आपको कारखाने को एक अलग घटक में स्थानांतरित करने के विकल्प के साथ छोड़ देता है, कार्यान्वयन को बाद में वसंत आदि के बिना काम करने के लिए बदल रहा है
डॉक्टर ब्राउन

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

यदि कार वाहन का बहुत सामान्य, मानक कार्यान्वयन है, तो यह एसआरपी का उल्लंघन नहीं है। वाहन के पास अभी भी केवल एक ही कारण है जिसे बदलने के लिए, जब Google एक autodrive()विधि जोड़ता है । आपकी बहुत ही सामान्य कार को उस विधि को लागू करने के लिए बदलना होगा, जैसे कि NotImplementedException को फेंककर, लेकिन यह वाहन पर बदलने के लिए एक अतिरिक्त कारण प्रदान नहीं करता है
209 बजे user949300

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

3

यह मेरे लिए नल ऑब्जेक्ट पैटर्न जैसा दिखता है ।

लेकिन यह बहुत हद तक इस बात पर निर्भर करता है कि Carकक्षा कैसे लागू की जाती है। यदि इसे "तटस्थ" तरीके से लागू किया जाता है, तो यह निश्चित रूप से अशक्त वस्तु है। इसका मतलब है, यदि आप इंटरफ़ेस पर सभी अशक्त जांच को हटा सकते हैं और प्रत्येक घटना के बजाय इस वर्ग का उदाहरण रख सकते हैं null, तो कोड को अभी भी सही ढंग से काम करना है।

इसके अलावा अगर यह यह पैटर्न है, तो इंटरफ़ेस के बीच तंग युग्मन बनाने और अशक्त वस्तु के कार्यान्वयन की कोई समस्या नहीं है। क्योंकि अशक्त वस्तु हर जगह हो सकती है जहाँ उक्त इंटरफ़ेस का उपयोग किया जाता है।


2
नमस्कार और उत्तर के लिए धन्यवाद। हालांकि मुझे पूरा यकीन है कि मेरे मामले में "नल ऑब्जेक्ट" पैटर्न को लागू करने के लिए इसका उपयोग नहीं किया गया था, यह एक दिलचस्प विवरण है।
जयराम
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.