java - नेस्टेड कॉलबैक के लिए जावा पैटर्न?





design-patterns asynchronous callback nested (5)


मुझे यकीन नहीं है कि क्या मैं आपको सही तरीके से प्रश्न पूछता हूं। यदि आप एक सेवा शुरू करना चाहते हैं और इसके पूरा होने पर परिणाम को अन्य ऑब्जेक्ट में पारित करने की आवश्यकता है जो परिणाम का उपयोग करके प्रसंस्करण जारी रख सकता है। आप इसे प्राप्त करने के लिए समग्र और पर्यवेक्षक का उपयोग कर देख सकते हैं।

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

public interface Request {} 

public interface Response {} 

public interface Callback<R extends Response> {
    void onSuccess(R response);
    void onError(Exception e);
}

Request और Response इंटरफेस के विभिन्न जोड़े कार्यान्वयन हैं, अर्थात् RequestA + ResponseA (क्लाइंट द्वारा दिया गया), RequestB + ResponseB (सेवा द्वारा आंतरिक रूप से उपयोग किया जाता है) इत्यादि।

प्रसंस्करण प्रवाह इस तरह दिखता है:

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

अब तक मैंने जावा में कोडिंग करने के लिए दो दृष्टिकोणों की कोशिश की है:

  • गुमनाम वर्ग: आवश्यक घोंसले की वजह से बदसूरत हो जाता है
  • आंतरिक कक्षाएं: उपरोक्त की तुलना में neater, लेकिन अभी भी निष्पादन के प्रवाह को समझने के लिए एक और डेवलपर के लिए मुश्किल है

क्या इस कोड को और अधिक पठनीय बनाने के लिए कुछ पैटर्न है? उदाहरण के लिए, क्या मैं सेवा पद्धति को स्व-निहित संचालन की सूची के रूप में व्यक्त कर सकता हूं जो कि कुछ ढांचे वर्ग द्वारा अनुक्रम में निष्पादित किया जाता है जो घोंसले की देखभाल करता है?




चूंकि कार्यान्वयन (न केवल इंटरफेस) ब्लॉक करना चाहिए, मुझे आपकी सूची विचार पसंद है।

"ऑपरेशंस" (शायद Future एस?) की एक सूची सेट करें, जिसके लिए सेटअप बहुत स्पष्ट और पठनीय होना चाहिए। फिर प्रत्येक प्रतिक्रिया प्राप्त करने पर, अगला ऑपरेशन लागू किया जाना चाहिए।

थोड़ी सी कल्पना के साथ, यह जिम्मेदारी की श्रृंखला की तरह लगता है। मैं जो कुछ कल्पना कर रहा हूं उसके लिए यहां कुछ छद्म कोड है:

public void setup() {
    this.operations.add(new Operation(new RequestA(), new CallbackA()));
    this.operations.add(new Operation(new RequestB(), new CallbackB()));
    this.operations.add(new Operation(new RequestC(), new CallbackC()));
    this.operations.add(new Operation(new RequestD(), new CallbackD()));
    startNextOperation();
}
private void startNextOperation() {
    if ( this.operations.isEmpty() ) { reportAllOperationsComplete(); }
    Operation op = this.operations.remove(0);
    op.request.go( op.callback );
}
private class CallbackA implements Callback<Boolean> {
    public void onSuccess(Boolean response) {
        // store response? etc?
        startNextOperation();
    }
}
...



मेरी राय में, इस तरह की समस्या का मॉडल करने का सबसे स्वाभाविक तरीका Future<V>

तो कॉलबैक का उपयोग करने के बजाय, बस "थंक" लौटाएं: एक Future<Response> जो उस प्रतिक्रिया का प्रतिनिधित्व करता है जो भविष्य में किसी बिंदु पर उपलब्ध होगा।

फिर आप Future<ResponseB> step2(Future<ResponseA>) जैसी चीजों के रूप में बाद के चरणों को मॉडल कर सकते हैं, या ListenableFuture<V> उपयोग Guava से कर सकते हैं। फिर आप अपने कार्यों को प्राकृतिक तरीके से चेन करने के लिए Futures.transform() या इसके Futures.transform() एक का उपयोग कर सकते हैं, लेकिन अभी भी एसिंक्रोनस प्रकृति को संरक्षित करते समय।

यदि इस तरह से उपयोग किया जाता है, तो Future<V> एक मोनड की तरह व्यवहार करता है (वास्तव में, मुझे लगता है कि यह एक के रूप में योग्य हो सकता है, हालांकि मुझे अपने सिर के ऊपर से यकीन नहीं है), और इसलिए पूरी प्रक्रिया आईओ की तरह महसूस करती है IOS monad के माध्यम से प्रदर्शन के रूप में Haskell में।




आप अभिनेता कंप्यूटिंग मॉडल का उपयोग कर सकते हैं। आपके मामले में, ग्राहक, सेवाएं, और कॉलबैक [बीडी] सभी को अभिनेताओं के रूप में प्रदर्शित किया जा सकता है।

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




केवल यादृच्छिक के बजाय SecureRandom का उपयोग करना बेहतर है।

public static int generateRandomInteger(int min, int max) {
    SecureRandom rand = new SecureRandom();
    rand.setSeed(new Date().getTime());
    int randomNum = rand.nextInt((max - min) + 1) + min;
    return randomNum;
}




java design-patterns asynchronous callback nested