2009-07-29 17 views
9

मैं एक साधारण चैट एप्लिकेशन (बस इसके किक के लिए) डिजाइन कर रहा हूं। मैं उस चैट एप्लिकेशन के लिए एक साधारण डिजाइन के बारे में सोच रहा हूं। आपको अवलोकन देने के लिए .. यहां नियम हैं:एक साधारण चैट एप्लिकेशन के लिए उपयुक्त डिजाइन पैटर्न

  1. बेनामी उपयोगकर्ता सिर्फ उपनाम के साथ चैट दर्ज करें। (उपयोगकर्ता आईडी) संभावित रूप से पृष्ठभूमि में सिस्टम द्वारा असाइन किया गया है।
  2. वे चैट वार्तालाप में शामिल हो सकते हैं (सदस्यता लें)। और वह नामित क्षेत्र में दिखाई देने वाले अन्य उपयोगकर्ताओं से चैट-टेक्स्ट देखेंगे।
  3. वे किसी विशेष बातचीत का जवाब दे सकते हैं और बाकी सभी को यह देखना चाहिए।

यह है कि! (मैंने आपको बताया कि यह एक साधारण चैट एप्लिकेशन था)। तो, मेरा इरादा वास्तव में आवेदन नहीं है; लेकिन इसमें डिजाइन पैटर्न और वस्तुओं का इस्तेमाल किया।

अब यह है कि मैंने इसे कैसे डिज़ाइन किया है। (मैं जावा में कोडिंग कर रहा हूँ .. ऐसा होता है कि वास्तव में मायने रखती में)

  1. उपयोगकर्ता ऑब्जेक्ट - दो गुण आईडी और उपनाम
  2. संदेश वस्तु - एक सरल संदेश इंटरफेस और कार्यान्वयन (अब के लिए) एक SimpleMessage के रूप में, एक साथ संदेश रखने के लिए विशेषता के रूप में स्ट्रिंग।
  3. चैट विंडो ऑब्जेक्ट - मूल रूप से उपयोगकर्ता और संदेशों की संरचना। चूंकि इसमें एक उपयोगकर्ता ऑब्जेक्ट और संदेश की सूची है।
  4. चैट सत्र - फिर से रचना। असल में यह चैट विंडोज की एक सूची होगी। प्रत्येक चैट विंडो चैट सत्र में पंजीकृत होती है। एक नया संदेश प्रकट होने पर चैट सत्र सभी चैट विंडो को सूचित करने के लिए ज़िम्मेदार है। (ऑब्जर्वर पैटर्न किसी को?)

ठीक है .. तो अब मैं लागू कर दिया है पर्यवेक्षक पैटर्न ChatWindow लागू "ChatListener" गपशप जो "सूचित (संदेश)" कहा जाता विधि है बनाकर। तो ChatSession प्रत्येक पंजीकृत ChatWindow को सूचित करता है।

अब कुछ ऐसी चीजें हैं जिन्हें मैं स्पष्ट करना चाहता/चाहती हूं। 1. चैट विंडो बंद होने पर और मुझे और अधिसूचनाएं नहीं मिलनी चाहिए, तो मुझे सभी चैट विंडो के लिए भी डी-रजिस्टर विधि की आवश्यकता है। इसका संभावित अर्थ यह है कि या तो मेरे पास "स्टेटिक" केंद्रीय पंजीकरण प्रबंधक होना चाहिए जिसमें केवल एक उदाहरण हो और फिर कोई भी चैट विंडो "चैट सत्र" आईडी प्रदान करके स्वयं को पंजीकृत करने में सक्षम हो। इसी कारण से, प्रत्येक चैट सत्र में एक आईडी होना चाहिए। (यहां शामिल)। या मैं चैट विंडो में चैटसेशन का एक उदाहरण भी बनाए रख सकता हूं, हमेशा एक उदाहरण तैयार करने के लिए। (मुझे सिंगलेट्स से नफरत है क्योंकि मुझे लगता है कि वे ओप्स के खिलाफ जाते हैं)। एक और तरीका चैट विंडो के साथ चैट विंडो का डी-पंजीकरण नियंत्रण नहीं होना चाहिए, इसके बजाय विंडो बंद करने की अधिसूचना सीधे चैट सत्र में आनी चाहिए और इसे करना चाहिए, इसे क्या करना चाहिए!

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

  2. साथ ही जब उपयोगकर्ता अपनी चैट विंडो में एक नया संदेश टाइप करता है; इसे सभी चैट विंडो के लिए प्रचारित करने की आवश्यकता है, जो चैट सत्र करता है, लेकिन साथ ही साथ; क्या इसका मतलब यह है कि .. चैट सत्र को "चैट विंडो आईडी" और संदेश के साथ एक संदेश प्राप्त करने की आवश्यकता है? और फिर यह सभी खिड़कियों के लिए प्रचार करता है, जिसमें संदेश का मालिक है? इसे संभालने का एक बेहतर तरीका क्या है।मेरा मतलब है, एक तरीका जहां विंडो चैट सत्र को संदेश के बारे में जानती है और फिर अन्य सभी विंडोज़ पर सत्र चैट करती है। (मैं इसे कुछ के यदि आवश्यकता होगी ... उन्हें या तो पसंद नहीं है सोच रहा हूँ)

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

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

package com.oo.chat; 

public class User { 

    private Long userId; 
    private String nickname; 

    public User(Long userId, String nickname) { 
     this.userId = userId; 
     this.nickname = nickname; 
    } 

    public void setUserId(Long userId) { 
     this.userId = userId; 
    } 

    public void setNickname(String nickname) { 
     this.nickname = nickname; 
    } 

    public Long getUserId() { 
     return userId; 
    } 

    public String getNickname() { 
     return nickname; 
    } 

    public boolean equals(Object objectToCompare) { 
     if (!(objectToCompare instanceof User)) { 
      return false; 
     } 
     User incoming = (User) objectToCompare; 
     if (incoming.getNickname() != null && incoming.getUserId() != null) { 
      if (incoming.getNickname().equalsIgnoreCase(this.nickname) 
        && incoming.getUserId().equals(this.userId)) 
       return true; 
     } 
     return false; 
    } 
} 


package com.oo.chat; 

public interface Message { 

    public String getValue(); 

    public void setValue(String value); 

} 

package com.oo.chat; 

public class SimpleMessage implements Message { 

    private String value; 

    public SimpleMessage() { 

    } 

    public SimpleMessage(String value) { 
     this.value = value; 
    } 

    public String getValue() { 
     return value; 
    } 

    public void setValue(String value) { 
     this.value = value; 
    } 
} 

package com.oo.chat; 

public interface ChatListener { 

    public void notify(Message newMessage); 

} 

package com.oo.chat; 

import java.util.ArrayList; 
import java.util.List; 

public class ChatWindow implements ChatListener { 

    private User user; 
    private List<Message> messageList; 
    private Long id; 

    public User getUser() { 
     return user; 
    } 

    public List<Message> getMessageList() { 
     return messageList; 
    } 

    public void setUser(User user) { 
     this.user = user; 
    } 

    public void setMessageList(List<Message> messageList) { 
     this.messageList = messageList; 
    } 

    public void addMessageToList(Message newMessage) { 
     if (this.messageList == null) { 
      this.messageList = new ArrayList<Message>(); 
     } 
     this.messageList.add(newMessage); 
    } 

    public void notify(Message newMessage) { 
     addMessageToList(newMessage); 
    } 

    public Long getId() { 
     return id; 
    } 

    public void setId(Long id) { 
     this.id = id; 
    } 
} 

package com.oo.chat; 

import java.util.ArrayList; 
import java.util.List; 

public class ChatSession { 

    private List<ChatListener> registeredChatListeners; 

    public void register(ChatWindow chatWindow) { 
     if (registeredChatListeners == null) 
      registeredChatListeners = new ArrayList<ChatListener>(); 
     registeredChatListeners.add(chatWindow); 
    } 

    public List<ChatListener> getRegisteredChatListeners() { 
     return registeredChatListeners; 
    } 

    public void setRegisteredChatWindows(
      List<ChatListener> registeredChatListeners) { 
     this.registeredChatListeners = registeredChatListeners; 
    } 

    public void incomingMessage(Long chatListenerId, Message message) { 
     publish(message); 
    } 

    protected void publish(Message messageToPublish) { 
     if (registeredChatListeners != null) { 
      for (ChatListener eachListener : registeredChatListeners) { 
       eachListener.notify(messageToPublish); 
      } 
     } 
    } 
} 

सभी योगदानकर्ताओं को अग्रिम धन्यवाद। चीयर्स

उत्तर

4

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

मैं यह भी देख आप उपयोगकर्ता आईडी के लिए एक सेटर है। तो क्या आप वास्तव में उपयोगकर्ता आईडी बदलना चाहते हैं? मैं देखता हूं कि आप उपनाम बदल सकते हैं, जो समझ में आता है। लेकिन मैं उम्मीद करता हूं कि आईडी स्थिर रहेगी।

भी ध्यान रखें कि आप बराबर अधिभावी रहे हैं के बाद से(), आप भी override hashCode() चाहिए।

अब, अगर hashCode() और बराबरी() अपरिवर्तनीय क्षेत्रों (जैसे आईडी) पर भरोसा करते हैं, तो) hashCode के परिणाम (परिवर्तन नहीं होगा, और आप एक टुकड़े किए गए संग्रह में एक उपयोगकर्ता डाल अगर (जैसे HashMap) तो आप इसे बाद में खोने वाले नहीं हैं (जो बहुत भ्रमित है)!

अंत में (!) मैं निरर्थक उपनामों के खिलाफ कन्स्ट्रक्टर और सेटर्स की रक्षा करता हूं (उन्हें अवैध अर्ग्यूमेंट अपवादों को फेंक देता है) और फिर बराबर() जैसे कोड को एक शून्य उपनाम के बारे में चिंता करने की ज़रूरत नहीं है (जब तक 'शून्य' का अर्थ न हो उपनाम)। मैं आईडी के लिए भी ऐसा ही करूंगा, क्योंकि आपके पास यह एक लंबी (वस्तु) है। लेकिन क्या यह एक आदिम लंबा नहीं हो सकता है?

+0

मूल्यवान प्रतिक्रिया के लिए बहुत बहुत धन्यवाद। यही वह है जिसे मैं बिल्कुल ढूंढ रहा था। मैं आपका जवाब सही के रूप में स्वीकार कर लेता, तुरंत! लेकिन मैं थोड़ी देर इंतजार करूंगा; अगर लोग अधिक उत्तरों के साथ आते हैं। :) – Priyank

+0

यह ठीक है। मैंने आपके द्वारा पूछे गए समग्र पैटर्न पर ध्यान केंद्रित नहीं किया है, इसलिए मुझे संदेह है कि अन्य उत्तर 'स्वीकृति' के लिए अधिक उपयुक्त हैं, लेकिन उपरोक्त को जानना अच्छा है –

6

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

कुछ महत्वपूर्ण डिजाइन मुद्दों कि मैं देख कर रहे हैं:

  1. संदेश इंटरफेस वापस नहीं जुड़ता है संदेश के प्रेषक - ज्यादातर चैट दिखाने के जो कहा क्या, और यह एक के बिना मुश्किल होगा संदेश में उपयोगकर्ता क्षेत्र।
  2. संदेश इंटरफ़ेस में समय संपत्ति नहीं है। इससे पुराने संदेशों को और अधिक कठिन बना दिया जाएगा।
+0

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

2

मैं ऑब्जर्वर पैटर्न का उपयोग करने के बजाय मैसेजिंग फ्रेमवर्क में देखने का सुझाव दूंगा। eventbus (अब उपलब्ध नहीं) -

इस सरल कार्यान्वयन जो अपने खिलौना परियोजना के लिए पर्याप्त होगा पर एक नजर डालें। वैकल्पिक रूप से आप ActiveMQ जैसे पूर्ण उड़ाए गए जेएमएस कार्यान्वयन के साथ जा सकते हैं।

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

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