2015-01-28 6 views
6

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

public abstract T execute() 
{ 
    ... 

    return T; 
} 

BaseOperation की उपवर्गों इस पद्धति को लागू करना चाहिए:: इस वर्ग में केवल एक ही सार विधि है,

public class GetUsersOperation extends BaseOperation<GetUsersResponse> 
{ 
    ... 

    @Override 
    public GetUsersResponse execute() 
    { 

     ... 

     return GetUsersResponse; 
    } 

} 

यह BaseOperation कक्षा में सभी आम "ऑपरेशन" तर्क डाल करने के लिए एक शानदार तरीका है लेकिन अभी भी हर कंक्रीट सबक्लास की execute() विधि में एक अलग रिटर्न प्रकार है।

अब मुझे इस संरचना को बदलने की आवश्यकता है ताकि निष्पादन() विधियों को तर्कों की एक परिवर्तनीय मात्रा हो सके। उदाहरण के लिए, एक ठोस उपवर्ग की आवश्यकता होगी:

execute(String, int) 

और एक अन्य की आवश्यकता होगी:

execute(Date, Date, String) 

यह मुश्किल है, क्योंकि निष्पादित विधि आधार वर्ग में घोषित किया जाता है। आधार में निष्पादन विधियों को अधिभारित करना आदर्श नहीं है। सबसे पहले, ओवरलोड की मात्रा बहुत बड़ी होगी। दूसरा, प्रत्येक सबक्लास केवल निष्पादन विधियों में से एक का उपयोग करेगा, अन्य सभी का क्या मतलब है?

(मेरी राय में) सबसे आसान समाधान varargs साथ विधि पर अमल की घोषणा करने के होगा:

execute(Object... arguments) 

और फिर उपवर्गों में सभी तर्कों खिन्न: जाहिर है

execute(Object... arguments) 
{ 
    String s = (String) arguments[0]; 
    ... 
} 

यह 2 प्रमुख है डाउनसाइड्स:

  • सभी डाउनकास्टिंग परिचालनों के कारण कम प्रदर्शन
  • execute() विधियों को कॉल करना अब सख्ती से टाइप नहीं किया गया है क्योंकि किसी भी मात्रा में ऑब्जेक्ट्स को वायरआउट कंपाइलर चेतावनियां पारित की जा सकती हैं।

क्या ऐसे पैटर्न या अन्य समाधान हैं जिनके पास इन नुकसान नहीं हो सकते हैं?

उत्तर

2

जैसा कि पहले से ही कहा गया है, आपकी समस्या को हल करने के लिए आम दृष्टिकोण एक बीन होल्डिंग पैरामीटर का उपयोग कर रहा है।लेकिन यहाँ, एक और समाधान है एक बिल्डर दृष्टिकोण के आधार पर:

public interface BaseOperation<T> { 
    public T execute(); 
} 

public class AddOperation implements BaseOperation<Integer> { 
    private int a, b; 

    public void setA(int arg){ 
    a = arg ; 
    return this; 
    } 

    public void setB(int arg){ 
    b = arg; 
    return this; 
    } 

    @Override 
    public Integer execute() { 
    return a+b ; 
    } 
} 

और फिर इस तरह इसका इस्तेमाल:

new AddOperation().setA(1).setB(2).execute(); 

आप की आवश्यकता है और इस तरह से वैकल्पिक पैरामीटर मिश्रण कर सकते हैं:

public class MultipleAddOperation implements BaseOperation<Integer> { 
    private int sum ; 

    public MultipleAddOperation(int requiredInt){ 
    sum = requiredInt; 
    } 

    public void add(int optionalInt){ 
    sum += optionalInt ; 
    return this; 
    } 

    @Override 
    public Integer execute(){ 
    return sum; 
    } 
} 

और इसलिए:

new MultipleAddOperation(5).add(1).add(2).execute(); 
+0

मुझे पसंद है कि आवश्यक इनपुट के संबंध में वह तर्क कैसे एक अलग बीन वर्ग के बजाय उपclass (आवश्यक सेट विधियों के साथ) के गुण (फ़ील्ड) के रूप में कोडित है। हालांकि, मुझे एप्रोपिएट पैरामीटर सेट किए बिना निष्पादन() को कॉल करने से रोक नहीं है। क्या इसे हल किया जा सकता है? – user1884155

+0

@ user1884155 हां, ऑपरेशन कन्स्ट्रक्टर में तर्क पारित करना, मेरा संपादन देखें;) – NiziL

+0

आह, जाहिर है। मैं इस समाधान को 'सरल' जावबीन समाधान पर पसंद करता हूं क्योंकि मेरे सभी पैरामीटर आवश्यक हैं और मैं अपने द्वारा किए जाने वाले प्रत्येक ऑपरेशन क्लास के लिए अतिरिक्त बीन क्लास पेश नहीं करना चाहता हूं। धन्यवाद! – user1884155

5

आप मापदंडों पकड़े एक सेम इस्तेमाल कर सकते हैं:

public interface BaseOperation<T, U> { 
    T execute(U input); 
} 

public class GetUsersOperation implements BaseOperation<GetUsersResponse, UserInput> { 

    @Override 
    public GetUsersResponse execute(UserInput input) { 
     Date date = input.getDate(); 
     return new GetUsersResponse(date); 
    } 

} 

आपका सार वर्ग केवल एक एकल सार विधि है: बेहतर एक अंतरफलक का उपयोग करें। आप कई इंटरफेस को कार्यान्वित कर सकते हैं जबकि आप केवल एक वर्ग का विस्तार कर सकते हैं।

+0

पीआर के लिए धन्यवाद जवाब जवाब। मेरी बेस क्लास में अन्य विधियां हैं, लेकिन इसमें केवल 1 पब्लिक विधि है। अन्य सभी निजी/संरक्षित विधियां अमूर्त नहीं हैं और लॉगिंग, संदेशों को पार्स करने जैसे सामान्य काम करते हैं। इंटरफेस में जावा 1.7 में वास्तविक कोड नहीं हो सकता है, इसलिए मुझे लगता है कि इसे एक इंटरफेस में बदलना संभव नहीं है। या मैं इस विषय पर गलत हूँ? – user1884155

+0

@ user1884155 नहीं, आप सही हैं, मैंने सोचा कि यह केवल एक ही सार विधि है। – sp00m

+1

इस बात के बारे में उत्सुक है कि क्यों कई कन्स्ट्रक्टर वाले वर्ग के बजाय एक बीन पसंद करेंगे? ओवरलोडेड कन्स्ट्रक्टर के साथ आप पैराम सेट करने वाली सभी अतिरिक्त लाइनों से बच सकते हैं, और स्वीकार्य पैरामीटर संयोजन और आवश्यक मानों का कुछ संकेत भी प्रदान कर सकते हैं। – Blegger

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