2015-06-18 6 views
7

मेरे पास एक ऑब्जेक्ट है जिसमें फ़ील्ड के रूप में कुछ सरणी हैं। यह वर्ग मोटे तौर पर इस तरह दिखता है:समान ऑब्जेक्ट गुण प्राप्त करने के लिए सामान्यीकृत विधि

public class Helper { 
    InsuranceInvoices[] insuranceInvoices; 
    InsuranceCollectiveInvoices[] insuranceCollectiveInvoices 
    BankInvoices[] bankInvoices; 
    BankCollectiveInvoices[] bankCollectiveInvoices; 
} 

चालान सभी प्रकार के एक आपसी मार्कर इंटरफ़ेस चालान है।
मुझे उन सभी चालानों को उन पर एक और विधि का आह्वान करने की आवश्यकता है।

Helper helperObject = new Helper(); 
// ... 

for (InsuranceInvoices invoice : helperObject.getInsuranceInvoices()) { 
    Integer customerId = invoice.getCustomerId(); 
    // ... 
} 
for (BankInvoices invoice : helperObject.getBankInvoices()) { 
    Integer customerId = invoice.getCustomerId(); 
    // ... 
} 

// repeat with all array fields 

समस्या यह है कि सभी चालानों में केवल मार्कर इंटरफ़ेस सामान्य होता है। विधि getCustomerID() एक पारस्परिक इंटरफ़ेस या कक्षा द्वारा परिभाषित नहीं है। यह एक ऐसा व्यवहार है जिसे मैं किसी दिए गए विनिर्देश के कारण नहीं बदल सकता।

फॉर-प्रत्येक-लूप के अंदर कोड पुनरावृत्ति कुछ ऐसा है जो मुझे बग करता है। मुझे चार अलग-अलग सरणी में सभी चालान वस्तुओं पर एक ही चीज़ करना है। इसलिए प्रत्येक के लिए चार-लूप जो अनावश्यक कोड को फहराते हैं।

क्या कोई तरीका है कि मैं एक सामान्य (निजी) विधि लिख सकता हूं? एक विचार था:

private void generalMethod(Invoice[] invoiceArray){ 
    // ... 
} 

लेकिन क्योंकि वर्ग चालान विधि getCusomterId() पता नहीं है इस चार instanceof चेकों की आवश्यकता होगी। इसलिए मुझे कुछ भी नहीं मिलेगा; विधि में अभी भी पुनरावृत्ति होगी।

मैं इस समस्या को सामान्य बनाने के हर संभावित समाधान के लिए आभारी हूं!

+1

हां, तो कक्षाएं सभी लागू 'Invoice' है, और सभी को लागू' getCustomerId', लेकिन ' getCustomerId 'चालान 'इंटरफ़ेस में नहीं है? आपको नाम से विधि तक पहुंचने और इसे आमंत्रित करने के लिए प्रतिबिंब का उपयोग करना होगा। इस बिंदु पर, 'चालान' इंटरफ़ेस काफी बेकार है। – njzk2

+0

'getInsuranceInvoices' प्राप्त करें, 'getBankInvoices' ... सभी चार चालानों की समान संख्या लौटाते हैं? – Rajesh

+3

मेरे पास एक सुझाव है ... उस व्यक्ति के लिए एक क्लाउबैट लागू करें जिसने 'चालान' इंटरफेस को एक मार्कर इंटरफ़ेस बनाया है, जो निर्दिष्ट करता है कि कौन से तरीके चालान आम हैं। – Powerlord

उत्तर

7

संभावित समाधान समस्या सामान्यीकरण करने के लिए (सबसे खराब करने के लिए सबसे अच्छा से आदेश दिया):

आवरण वर्ग

public class InvoiceWrapper { 
    private String customerID; 
    public String getCustomerID() { 
     return customerID; 
    } 
    public InvoiceWrapper(BankInvoices invoice) { 
     this.customerID = invoice.getCustomerID(); 
    } 
    public InvoiceWrapper(InsuranceInvoices invoice) { 
     this.customerID = invoice.getCustomerID(); 
    } 
    // other constructors 
} 

Upd का उपयोग अगर मैं सही ढंग से समझ, आप के साथ कुछ करने की ज़रूरत है सभी सरणी में आईडी।इनवॉइसवापर का उपयोग करने के लिए, आपको हेल्पर क्लास में इटरेटर को भी लागू करने की आवश्यकता है, जो सरणी के माध्यम से चलती है और प्रत्येक प्रविष्टि के लिए एक रैपर लौटाती है। तो, आपके पास कोड होगा जो 4 सरणी के साथ काम करता है।

डाले

public class CustomerIdHelper { 
    public static String getID(Invoice invoice) { 
     if (invoice instanceof InsuranceInvoices) { 
      return ((InsuranceInvoices) invoices).getCustomerID(); 
     } else if ... 
    } 
} 

प्रतिबिंब के माध्यम से नाम से तरीकों कॉलिंग का उपयोग करते हुए उदाहरण

public class CustomerIdHelper { 
    public static String getID(Invoice invoice) { 
     Method method = invoice.getClass().getDeclaredMethod("getCustomerId"); 
     return (String) method.invoke(invoice); 
    } 
} 
+0

आपके सुझावों के लिए धन्यवाद! पहला दृष्टिकोण ऐसा कुछ है जिसे मैंने ध्यान में नहीं लिया था। लेकिन क्या आप मुझे समझा सकते हैं कि आपने तीनों में से सबसे खराब होने के लिए प्रतिबिंब दृष्टिकोण क्यों चुना? – DeMo

+1

@DeMo ऐसा इसलिए है क्योंकि अगर कोई विधि हटा देता है, तो आप इसे नोटिस नहीं करेंगे। पहले दो प्रकारों में आप संकलन त्रुटि देखेंगे। – AdamSkywalker

2

यह बहुत नहीं है, लेकिन आप उपयोग प्रतिबिंब अप getCustomerIdMethod और फिर invoke() यह देखने के लिए कर सकता है, cf Class.getDeclaredMethod()

private void generalMethod(Invoice[] invoiceArray){ 
    try { 
    for (Invoice invoice : invoiceArray) { 
     Method getCustomerId = invoice.getClass().getDeclaredMethod("getCustomerId"); 
     getCustomerId.invoke(invoice); 
    } 
    } catch (Exception e) { 
    // ... 
    } 
} 

ध्यान दें कि इस अपरीक्षित है करो।

2

यदि आपको कक्षाओं को बदलने की अनुमति नहीं है तो आप उन्हें एक कस्टम इंटरफ़ेस जोड़कर हैंडलिंग कर रहे हैं। सबसे अच्छी बात यह है कि आप उन्हें एक कस्टम क्लास के साथ लपेट सकते हैं जिसमें वांछित गुण हों।

इस तरह आपके पास एक 'कक्षा इतना अच्छा' कोड वाला एक वर्ग होगा जो कक्षाओं को परिवर्तित करता है जो आप उचित वर्गों से मेल नहीं खाते हैं जो उचित और उपयोगी डिज़ाइन से मेल खाते हैं।

उदाहरण के लिए आपके पास कक्षा WrappedInsuranceInvoice हो सकती है जो WrappedInsurace तक फैली हुई है और सदस्य क्षेत्र InsuranceInvoice है। यदि आपको मूल वर्ग को रखने की आवश्यकता नहीं है तो आप डेटा की प्रतिलिपि बनाकर भी बेहतर हो जाएंगे। इस तरह आप उदाहरण के लिए सरणी खो सकते हैं और सूचियों का उपयोग कर सकते हैं।

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

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