2012-03-08 18 views
5

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

// Method invoked e.g. in response to the user choosing a menu item 
void execute(Event event) { 
    // This code is executed on the client, and now we need some info off the server: 
    server.execute(new RemoteRequest() { 
     public void run() { 
      // This code is executed on the server, and we need to update the client 
      // GUI with current progress 
      final Result result = doSomeProcessing(); 
      client.execute(new RemoteRequest() { 
       public void run() { 
        // This code is again executed on the client 
        updateUi(result); 
       } 
      } 
     } 
    }); 
} 

हालांकि, बाद से server.execute एक क्रमबद्धता (यह एक दूरस्थ मशीन पर निष्पादित किया जाता है) का अर्थ है, इस पद्धति पूरी किए बिना संभव नहीं है कक्षा serializable (RemoteRequest आंतरिक वर्ग स्थिर नहीं हैं (बस स्पष्ट होने के लिए: यह एक आवश्यकता नहीं है कि Request कार्यान्वयन आवेदन के लिए माता-पिता के उदाहरण के लिए मूल उदाहरण तक पहुंच सकता है)

बेशक , एक समाधान अनुरोध और प्रतिक्रिया के लिए अलग (संभवतः स्थैतिक आंतरिक) कक्षाएं बनाना है, लेकिन इससे पठनीयता को नुकसान पहुंचाता है और इसे कठिन बनाना मुश्किल हो जाता है निष्पादन प्रवाह को मिटा दें।

मैंने इस समस्या को हल करने के लिए कोई मानक पैटर्न खोजने की कोशिश की है, लेकिन मुझे कुछ भी नहीं मिला है जो पठनीयता के बारे में मेरी चिंता का उत्तर देता है।

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

String personName = nameField.getText(); 
async exec on server { 
    String personAddress = database.find(personName); 
    async exec on client { 
     addressField.setText(personAddress); 
    } 
    Order[] orders = database.searchOrderHistory(personName); 
    async exec on client { 
     orderListViewer.setInput(orders); 
    } 
} 

अब मैं स्पष्ट कर देना चाहते कि अंतर्निहित:

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

+0

यह जेएम से कैसे संबंधित है? क्या यह कोड क्लाइंट या सर्वर या किसी अन्य मशीन पर निष्पादित है? – Andrejs

+0

हां, यह है। ऐसे मामले हैं जहां क्लाइंट और सर्वर पर कोड निष्पादित किया जाता है। ऐसे मामले भी हैं जहां क्लाइंट सर्वर पर कुछ निष्पादित करता है जो बदले में क्लाइंट पर कुछ निष्पादित करता है। – Krumelur

+0

मुझे लगता है कि हमें थोड़ा और विवरण चाहिए। क्या अनुरोध है/अपनी खुद की कक्षाओं का जवाब दें या वे कुछ ढांचे का हिस्सा हैं? निष्पादन वास्तव में क्या करता है? – Andrejs

उत्तर

0

मैं वास्तव में एक कस्टम धारावाहिक के साथ बेस क्लास बनाकर इसे हल कर रहा हूं जो इसका ख्याल रखता है। मुझे अभी भी उम्मीद है कि यह अंततः भाषा में हल हो जाएगी।

1

मेरी प्राथमिकता Command Pattern और जेनेरिक असिंक्रोनस कॉलबैक का उपयोग करना है। इस तरह के दृष्टिकोण का उपयोग सर्वर के साथ संचार करने के लिए जीडब्ल्यूटी में किया जाता है, उदाहरण के लिए। कमांड Serializable हैं, AsyncCallback एक इंटरफ़ेस है।

इन पंक्तियों के साथ

कुछ:

// from the client 
    server.execute(new GetResultCommand(args), new AsyncCallback<Result>() 
      { 
       public void onSuccess(Result result) { 
        updateUi(); // happens on the client 
       } 
      }); 

सर्वर फिर एक आदेश, प्रक्रिया इसे प्राप्त करने और परिणाम के साथ एक उचित प्रतिक्रिया जारी करने की जरूरत है।

+0

इस मामले में, 'AsyncCallback' एक गैर स्थैतिक आंतरिक कक्षा नहीं होगी? बाह्य वर्ग को क्रमबद्ध करने की आवश्यकता के बिना सर्वर को यह क्रमबद्ध कैसे किया जाता है? – Krumelur

+0

AsyncCallback को क्रमबद्ध करने और भेजने की आवश्यकता नहीं होगी। 'सर्वर' ऑब्जेक्ट केवल इसके संदर्भ में रहता है और फिर जब ऑब्जेक्ट वास्तविक सर्वर से आता है तो उसे कॉल करता है। केवल कमान और परिणाम केवल Serializable होने की जरूरत है। – Andrejs

+0

आपके पास एक अच्छी बात है, हालांकि मेरी समस्या यह है कि मैं 'GetResultCommand' को अज्ञात वर्ग के रूप में ऑनलाइन होना चाहता था, और' AsyncCallback' मेरे लिए उतना महत्वपूर्ण नहीं है (हालांकि यह अच्छा होगा)। – Krumelur

0

मैं दूसरे दिन इसी तरह की समस्या में भाग गया। एक ऐसा समाधान है जो अज्ञात वर्गों का उपयोग करता है (और इस प्रकार आपको स्थिर आंतरिक कक्षाओं को परिभाषित करने की आवश्यकता नहीं होती है), फिर भी उन अज्ञात वर्गों को स्थैतिक बना दिया जाता है (और इस प्रकार बाहरी वस्तु का संदर्भ नहीं दिया जाता है)।

, बस इस तरह, एक स्थिर विधि में गुमनाम वर्गों को परिभाषित:

void execute(Event event) { 
    static_execute(server, client, event); 
} 

// An anonymous class is static if it is defined in a static method. Let's use that. 
static void static_execute(final TheServer server, final TheClient client, final Event event) { 
    server.execute(new RemoteRequest() { 
     public void run() { 
      final Result result = doSomeProcessing(); 
      // See note below! 
      client.execute(new RemoteRequest() { 
       public void run() { 
        updateUi(result); 
       } 
      }); 
     } 
    }); 
} 

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

- इसके बारे में सोचने के लिए आओ, सर्वर-> ग्राहक दिशा के लिए, एक ही चाल को शायद एक बार और लागू करने की आवश्यकता है। मैं इसे पाठक के लिए एक अभ्यास के रूप में छोड़ दूंगा :-)

+0

इसका उल्लेख करने के लिए धन्यवाद। मैंने इस तरह का एक समाधान माना, लेकिन यह पता चला कि कोड मेरे मामले में और भी जटिल हो गया है, इस तरह लिखा है। – Krumelur

0

पहला: पैटर्न के बिना, यदि मैं सुझाव दूंगा, तो आप सभी पैटर्न को संभालने के लिए एक अलग वर्ग बना सकते हैं। बस एक वर्ग में ऑब्जेक्ट उत्पन्न किए गए प्रत्येक ईवेंट का उदाहरण पास करें और अन्य वर्गों के ईवेंट अनुरोध को प्रतिनिधि दें। प्रतिनिधिमंडल बहुत स्पष्ट दृष्टिकोण का कारण बनता है, केवल उदाहरण का उपयोग करने के लिए आवश्यक है और फिर आगे प्रतिनिधि। प्रत्येक घटना एक अलग जगह पर संक्षिप्त हो सकती है। उपर्युक्त दृष्टिकोण के साथ, हां, COMMAND पैटर्न निश्चित रूप से अनुरोधों को लॉग करने का एक अच्छा विकल्प है लेकिन आप उठाए गए प्रत्येक अनुरोध के लिए EVENT राज्य प्राप्त कर रहे हैं, इसलिए आप राज्य पैटर्न का प्रयास कर सकते हैं क्योंकि यह किसी ऑब्जेक्ट को अपने व्यवहार को बदलने के दौरान अपने व्यवहार को बदलने की अनुमति देता है।

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