2009-07-29 2 views
9

간단한 채팅 응용 프로그램을 디자인 중입니다. 나는 그 채팅 응용 프로그램에 대한 간단한 디자인 궁금했습니다. 개요를 제공하려면 여기에 규칙이 있습니다.간단한 채팅 응용 프로그램에 적합한 디자인 패턴

  1. 익명 사용자는 닉네임으로 채팅합니다. (사용자 ID)는 아마도 백그라운드에서 시스템에 의해 할당됩니다.
  2. 그들은 채팅 대화에 참여할 수 있습니다. 그리고 그는 지정된 영역에 나타나는 다른 사용자의 채팅 텍스트를 보게됩니다.
  3. 그들은 특정 대화에 응답 할 수 있으며 다른 모든 사람들은이를 볼 수 있습니다.

그거! (내가 간단한 채팅 응용 프로그램이라고 말했을 참조하십시오). 그래서, 제 의도는 실제로 응용 프로그램이 아닙니다. 그러나 그것에 사용 된 디자인 패턴과 객체들.

이제 어떻게 설계 했습니까? 두 속성 ID 및 별명

  • 메시지 개체 - - 간단한 메시지 인터페이스와 SimpleMessage으로 (지금은) 구현하는와

    1. 사용자 개체 (정말 중요한 경우에는 .. 자바로 코딩하고) 메세지를 포함하는 속성으로서의 캐릭터 라인
    2. 채팅 창 개체 - 기본적으로 사용자 및 메시지의 구성입니다. 하나의 사용자 객체와 메시지 목록을 가지고 있기 때문에.
    3. 채팅 세션 - 다시 구성. 기본적으로 채팅 창 목록이 있습니다. 각 채팅 창은 채팅 세션에 등록됩니다. 채팅 세션은 새 메시지가 나타나면 모든 채팅 창에 알릴 책임이 있습니다. (Observer pattern anyone?)

    좋아요. 이제는 ChatWindow에서 "notify (Message)"라는 메서드가있는 "ChatListener"패턴을 구현하여 관찰자 패턴을 구현했습니다. 따라서 ChatSession은 등록 된 모든 ChatWindow에 통지합니다.

    여기에 내가 명확히하고 싶거나 의견을 말하고 싶은 몇 가지 사항이 있습니다. 1. 채팅 창을 닫은 상태에서 더 이상 알림을받지 않으려는 경우 모든 채팅 창에도 등록 취소 방법이 있어야합니다. 즉, 하나의 인스턴스 만있는 "정적"중앙 등록 관리자가 있어야하며 모든 채팅 창은 "채팅 세션"ID를 제공하여 자체 등록을 취소 할 수 있어야합니다. 따라서 각 채팅 세션에는 ID가 있어야합니다. (여기 포함). 또는 채팅 창에서 ChatSession의 인스턴스를 유지 관리하여 항상 인스턴스를 준비 할 수 있습니다. (나는 그들이 죄송하다고 생각하면서 싱글 톤을 싫어한다.) 또 다른 방법은 채팅 창을 사용하지 않고 채팅 창 등록 취소 제어를하지 않는 것입니다. 대신 창 폐쇄 알림이 ChatSession에 직접오고 처리해야합니다.

    1. 이 디자인은 전혀 의미가 있습니까? CRAP이라고 말하면서 나에게 더 나은 접근 방식을 제공합니다. 너는 나에게 큰 감사를 얻을거야. 관찰자 패턴 외에도 모든 패턴을 단순화하거나 더 좋게 만들 수있는 패턴을 여기에 사용할 수 있습니다. 또한 .. 적절하다면이 디자인의 약점을 개선 할 수 있습니다.

    2. 또한 사용자가 자신의 채팅 창에 새 메시지를 입력 할 때; 그것은 채팅 세션이하는 일이지만 동시에, 모든 채팅 창으로 전파 될 필요가 있습니다. 채팅 세션이 "채팅 창 ID"와 메시지가있는 메시지를 받아야한다는 의미입니까? 그리고 나서 메시지의 소유자 인 것을 포함하여 모든 창으로 그것을 전파합니다. 이것을 처리하는 더 좋은 방법은 무엇입니까?내 말은, 창에서 채팅 세션이 메시지를 알 수있게 한 다음 다른 모든 창으로 세션을 채팅하는 방법입니다. (나는 그것을 필요로 할 것이라는 점을 생각하고있다 ... 그들 중 하나를 좋아하지 않는다.)

      어쨌든 ... 귀하의 의견을 알려주십시오. 또한 rem을 부탁드립니다. 작업 응용 프로그램이 의도가 아니라, 좋은 토론, 좋은 디자인 패턴 실습 및 사용법을 찾고 있습니다.

    높은 코드를 제공하는 경우 아래의 전체 코드를 읽어보십시오 ... 거의 모든 의미와 관련된 문제를 자유롭게 가져 오십시오.

    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 개체를 보면 왜 균등 함은 id 닉네임에 달려 있습니까? 그것은 나에게 직관력이없는 약간의 카운터처럼 보입니다. 나는 당신이 ID를 가지고 있다면 기대할 것입니다, 그리고 그것은 객체의 식별이며, 따라서 당신이 평등 상태에서 사용할 것입니다.

    사용자 ID에 대한 설정자가 있습니다. 그래서 정말로 사용자 ID를 변경하고 싶습니까? 나는 당신이 닉네임을 바꿀 수 있다는 것을 알고있다. 그러나 나는 이드가 계속 변하지 않을 것으로 기대한다.

    또한 equals()를 재정의 했으므로 override hashCode()이어야합니다.

    이제 hashCode() 및 equals()가 immable 필드 (예 : id)에 의존하면 hashCode()의 결과가 변경되지 않으며 사용자를 해시 콜렉션 (예 : HashMap) 그러면 나중에 잃지 않을 것입니다 (이것은 매우 혼란 스럽습니다)!

    마침내 (!) 나는 NULL 닉네임 (생성자가 IllegalArgumentExceptions를 던지도록)을 생성 한 다음 equals()와 같은 코드를 null 닉네임에 대해 걱정할 필요가없는 ('null'이 의미가 없다면) 별명). 나는 이드에게 똑같이 할 것이다. 왜냐하면 너는 이것을 롱 (객체)으로 가지고 있기 때문이다. 그러나 이것이 원시적 인 것일 수는 없었습니까?

    +0

    귀중한 의견을 보내 주셔서 감사합니다. 이것은 내가 정확히 찾고 있었던 것이다. 나는 당신의 대답을 바로 받아 들였을 것입니다. 그러나 나는 잠시 기다릴 것이다. 사람들이 더 많은 답변을 내놓을 경우를 대비해 :) – Priyank

    +0

    괜찮습니다. 나는 당신이 물었 듯이 전반적인 패턴에 초점을 맞추지 않았기 때문에 다른 대답이 '수용'에 더 적합하다고 의심하지만 위의 내용을 알고 있으면 유용합니다. –

    6

    기본 디자인은 나에게 소리가납니다. 분명히 이것을 완성하기 위해 더 많은 기능을 추가 할 필요가 없습니다. 현재 디자인은 모든 메시지를 무기한으로 유지하지만, 어떤 시점에서는 오래된 메시지를 제거하는 코드가 필요할 것입니다. 내가보고 할

    소수의 중요한 설계 문제는 다음과 같습니다

    1. 메시지 인터페이스가 다시 연결하지 않고 메시지를 보낸 사람 - 대부분의 채팅이 보여이이없이 어려운 것입니다 무엇을 말했다 메시지의 사용자 필드.
    2. 메시지 인터페이스에 time 속성이 없습니다. 이렇게하면 오래된 메시지를 제거하는 것이 더 어려워집니다.
    +0

    예 .. 두 점에 모두 동의합니다. 그러나 .. 만약 당신이 그것을 보았다면, 현재의 메시지는 어떤 사용자가 그것을 보낸지 타임 스탬프가 없다는 것을 알 수 있습니다. 보다 포괄적 인 impl 클래스를 사용하여 Message 인터페이스에 대한 impl을 수행 할 계획이었습니다. 아마 타임 스탬프와 발신자를 추가합니다. 메시지를 지속하는 것에 관해서는 제 마음을 교차 시켰습니다. 그러나 그 부분이나 UI는 구현하지 않았기 때문에 실제로 응용 프로그램을 개발하려고하지는 않았지만 지금은 기본으로 사용할 수 있습니다 물건. 디자인 패턴 학습의 폭을 넓혔습니다. 그런 말로는 감사드립니다. 감사합니다. – Priyank

    2

    옵서버 패턴을 사용하는 대신 메시징 프레임 워크를 조사해 보시기 바랍니다.

    장난감 프로젝트에 충분한이 간단한 구현 - eventbus (더 이상 제공되지 않음)을 살펴보십시오. 또는 ActiveMQ과 같이 완전히 구현 된 JMS 구현을 사용할 수도 있습니다.

    기본적으로 참가자를 등록하고 등록을 취소 할 수있는 공통 버스를 정의 할 수 있으며 모든 참가자에게 표시되는 메시지도 보낼 수 있습니다. 관찰자 패턴에 비해 큰 장점은 참여자 간의 매우 낮은 결합입니다. 즉, 메시지를 받기 위해 각 객체에 등록하지 않고 버스로 등록하면됩니다. 또한 비동기 처리 - 1000 개의 채팅 세션이 있다고 가정 해 봅시다 - 옵서버를 사용하면 완료 할 각 메시지가 1000 회의 세션을 업데이트하는 것을 의미합니다. 메시지 프레임 워크를 사용하면 메시지 보내기가 매우 빠르며 1000 개의 세션을 모두 백그라운드에서 알릴 수 있습니다.

    관련 문제