जावा में कई मापदंडों के साथ बिल्डरों का प्रबंधन करना


105

हमारी कुछ परियोजनाओं में, एक श्रेणी पदानुक्रम है जो श्रृंखला में नीचे जाने के साथ अधिक पैरामीटर जोड़ता है। तल पर, कुछ वर्गों में 30 पैरामीटर तक हो सकते हैं, जिनमें से 28 बस सुपर कंस्ट्रक्टर में पारित किए जा रहे हैं।

मैं स्वीकार करता हूँ कि Guice जैसी किसी चीज़ के माध्यम से स्वचालित DI का उपयोग करना अच्छा होगा, लेकिन कुछ तकनीकी कारणों के कारण, ये विशिष्ट परियोजनाएँ Java के लिए विवश हैं।

प्रकार द्वारा तर्क को व्यवस्थित करने का एक सम्मेलन काम नहीं करता है क्योंकि यदि एक प्रकार को रिफैक्ट किया जाता है (आप जिस सर्किल को तर्क 2 के लिए पारित कर रहे थे वह अब एक आकृति है) यह अचानक क्रम से बाहर हो सकता है।

यह प्रश्न "यदि आपकी समस्या है, तो आप विशिष्ट हैं और यह एक डिज़ाइन स्तर पर गलत हो रहा है" आलोचनाओं के साथ हो सकता है, लेकिन मैं सिर्फ किसी भी दृष्टिकोण की तलाश कर रहा हूं।

जवाबों:


264

बिल्डर डिज़ाइन पैटर्न मदद कर सकता है। निम्नलिखित उदाहरण पर विचार करें

public class StudentBuilder
{
    private String _name;
    private int _age = 14;      // this has a default
    private String _motto = ""; // most students don't have one

    public StudentBuilder() { }

    public Student buildStudent()
    {
        return new Student(_name, _age, _motto);
    }

    public StudentBuilder name(String _name)
    {
        this._name = _name;
        return this;
    }

    public StudentBuilder age(int _age)
    {
        this._age = _age;
        return this;
    }

    public StudentBuilder motto(String _motto)
    {
        this._motto = _motto;
        return this;
    }
}

इससे हम जैसे कोड लिखते हैं

Student s1 = new StudentBuilder().name("Eli").buildStudent();
Student s2 = new StudentBuilder()
                 .name("Spicoli")
                 .age(16)
                 .motto("Aloha, Mr Hand")
                 .buildStudent();

यदि हम एक आवश्यक फ़ील्ड छोड़ देते हैं (संभवतः नाम आवश्यक है) तो हमारे पास छात्र कंस्ट्रक्टर को एक अपवाद फेंक सकता है। और यह हमें किसी भी प्रकार के तर्क क्रम का ट्रैक रखने की आवश्यकता के बिना डिफ़ॉल्ट / वैकल्पिक तर्क देता है, क्योंकि उन कॉलों का कोई भी आदेश समान रूप से अच्छी तरह से काम करेगा।


10
निश्चित रूप से स्थिर आयात के साथ आपको कभी भी "इन" बिल्डरों को "देखना" बिल्कुल भी नहीं है। उदाहरण के लिए, आपके पास स्टैटिक विधियों का नाम (स्ट्रिंग नाम) हो सकता है, जो एक बिल्डर और छात्र (स्टूडेंटबर्स्टल) देता है जो एक छात्र को लौटाता है। इसलिए छात्र (नाम ("जो")। उम्र (15)। आदर्श वाक्य ("मैंने खुद को गीला कर दिया है"));
०१

2
@oxbow_lakes: आपके उदाहरण में, किस कक्षा में स्थैतिक विधि का नाम (स्ट्रिंग नाम) है?
user443854

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

1
@WVrock: यह आपके कार्यान्वयन पर निर्भर करता है। जैसा कि मैं अपने उत्तर में कहता हूं, छात्र वर्ग के साथ ऐसा करने से संभवतः कक्षा को एक प्रारंभिक-प्रारंभिक स्थिति में छोड़ दिया जा सकता है, उदाहरण के लिए यदि आपके पास एक आवश्यक फ़ील्ड है जिसे अभी तक प्रारंभ नहीं किया गया है।
एली कोर्टराइट 15

@EliCourtwright मुझे लगता है कि यह वरीयता / कोड डिज़ाइन के बारे में है। इसके बजाय कंस्ट्रक्टर को अपवाद बनाने के बजाय मैंने buildStudent()विधि को अपवाद बना दिया ।
WVrock

24

क्या आप किसी वस्तु के अंदर संबंधित मापदंडों को संलग्न कर सकते हैं?

उदाहरण के लिए, यदि पैरामीटर पसंद हैं


MyClass(String house, String street, String town, String postcode, String country, int foo, double bar) {
  super(String house, String street, String town, String postcode, String country);
  this.foo = foo;
  this.bar = bar;

तो आप के बजाय हो सकता है:


MyClass(Address homeAddress, int foo, double bar) {
  super(homeAddress);
  this.foo = foo;
  this.bar = bar;
}


14

आप जो करना चाहते हैं, वह एक बिल्डर वर्ग है। फिर आप कुछ इस तरह करेंगे:

MyObject obj = new MyObjectBuilder().setXxx(myXxx)
                                    .setYyy(myYyy)
                                    .setZzz(myZzz)
                                    // ... etc.
                                    .build();

पृष्ठ 8 देखें और इस जोश बलोच प्रस्तुति (पीडीएफ), या प्रभावी जावा की इस समीक्षा के बाद


8

ठीक है, बिल्डर पैटर्न का उपयोग करना एक समाधान हो सकता है।

लेकिन एक बार जब आप 20 से 30 मापदंडों पर आते हैं, तो मुझे लगता है कि मापदंडों के बीच एक उच्च संबंध है। तो (जैसा कि सुझाव दिया गया है) उन्हें तार्किक रूप से समझदार डेटा-ऑब्जेक्ट्स में लपेटना संभवतः सबसे अधिक समझ में आता है। इस तरह से डेटा ऑब्जेक्ट पहले से ही मापदंडों के बीच बाधाओं की वैधता की जांच कर सकता है।

अतीत में मेरी सभी परियोजनाओं के लिए, एक बार जब मैं इस बिंदु पर आया था तो बहुत सारे पैरामीटर थे (और वह 8 नहीं 28 था!) ​​मैं एक बेहतर डेटामॉडल बनाकर कोड को पवित्र करने में सक्षम था।


4

जैसा कि आप जावा 1.4 के लिए विवश हैं, यदि आप DI चाहते हैं तो स्प्रिंग एक बहुत ही अच्छा विकल्प होगा। DI केवल उन स्थानों में सहायक है जहां निर्माण पैरामीटर सेवाओं या कुछ ऐसा है जो रनटाइम के दौरान भिन्न नहीं होता है।

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


पैरामीटर ज्यादातर सेवाओं के रूप में आप उल्लेख किया है, और इसलिए DI है कि मैं क्या जरूरत होगी। मुझे लगता है कि बिल्डर पैटर्न का उल्लेख कुछ अन्य उत्तरों में किया गया है, वही है जिसकी मैं उम्मीद कर रहा था।
स्टीव आर्मस्ट्रांग

4

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



1

मापदंडों की संख्या को कम करने और आप की विरासत पदानुक्रम की गहराई बहुत ज्यादा है, क्योंकि मैं सोच सकता हूं कि वास्तव में, 20-कुछ मापदंडों को सीधा रखने में मदद करने के लिए कुछ भी नहीं है। आप दस्तावेज़ देखने के दौरान हर एक कॉल पर जा रहे हैं।

एक चीज जो आप कर सकते हैं, वह है कुछ तार्किक रूप से समूहित मापदंडों को अपने उच्च स्तर की वस्तु में समूहित करना, लेकिन इसकी अपनी समस्याएं हैं।

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.