适用于简单聊天应用程序的设计模式

Pri*_*ank 10 java design-patterns

我正在设计一个简单的聊天应用程序(只是为了它的一脚).我一直想知道这个聊天应用程序的简单设计.为了给你概述..这里是规则:

  1. 匿名用户只使用昵称进入聊天.(用户ID)可能是由系统在后台分配的.
  2. 他们可以加入(订阅)聊天对话.他会看到其他用户的聊天文本出现在指定区域.
  3. 他们可以回复特定的对话,其他人都应该看到.

而已!(见我告诉过你这是一个简单的聊天应用程序).所以,我的意图并不是真正的应用; 但其中使用的设计模式和对象.

现在我就是这样设计的.(我在java编码..如果真的很重要)

  1. 用户对象 - 两个属性id和昵称
  2. 消息对象 - 一个简单的Message接口和实现(现在)作为SimpleMessage,其中String作为包含消息的属性.
  3. 聊天窗口对象 - 基本上是用户和消息的组合.因为它有一个用户对象和消息列表.
  4. 聊天会话 - 再次组成.基本上它会有一个Chat Windows列表.每个聊天窗口都注册到聊天会话.聊天会话负责在出现新消息时通知所有聊天窗口.(观察者模式有人吗?)

好吧..所以现在我已经通过使ChatWindow实现"ChatListener"模式实现了观察者模式,该模式具有称为"通知(消息)"的方法.所以ChatSession会通知每个注册的ChatWindow.

现在这里有一些我想澄清/想要你的意见的事情.1.我还需要为所有聊天窗口取消注册方法,以防聊天窗口关闭并且不想再收到任何通知.这可能意味着,要么我应该有一个"静态"中央注册管理器,它只有一个实例,然后任何聊天窗口应该能够通过提供"聊天会话"ID来取消注册自己.因此,每个聊天会话都应该有一个id.(包括在内).或者我也可以在聊天窗口中维护ChatSession的实例,以便始终准备好实例.(我讨厌单身,因为我认为他们反对哎呀).另一种方法是没有取消注册控制聊天窗口,使用聊天窗口,而窗口关闭的通知应直接进入ChatSession,它应该做什么,应该做什么!

  1. 这个设计有意义吗?如果你说这是一个CRAP并给我一个更好的方法; 你一定会非常感谢我.除了观察者模式之外,这里可以使用所有模式来简化它或使其更好.此外..这个设计的任何弱点,如果它是合适的,但可以改进.

  2. 此外,当用户在他自己的聊天窗口中键入新消息时; 它需要传播到所有聊天窗口,这是聊天会话所做的,但同时; 这是否意味着..聊天会话需要获得带有"聊天窗口ID"和消息的消息?然后它将它传播到所有窗口,包括作为邮件所有者的窗口?有什么更好的方法来处理这个问题.我的意思是,窗口让聊天会话知道消息,然后聊天会话到所有其他窗口.(我觉得它需要一些,如果......也不喜欢它们)

    无论如何......请告诉我你的意见.还请你.工作应用程序不是意图,我正在寻找一个很好的讨论,良好的设计模式实践和用法.

下面的完整代码,如果它给你一个高...随意拆开它并提出几乎任何语义相关的问题.

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);
            }
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

感谢所有贡献者提前.干杯

jsi*_*ght 6

基本设计看起来很合理.显然要完成这个,你需要添加更多的功能.当前设计将所有消息无限期地保存在内存中,但在某些时候,您将需要用于清除旧消息的代码.

我看到的几个重要的设计问题是:

  1. 消息接口不链接消息的发送者 - 大多数聊天显示谁说了什么,如果没有消息中的用户字段,这将很难.
  2. 消息接口没有时间属性.这将使清除旧邮件变得更加困难.


Bri*_*new 5

仅查看User对象,为什么平等取决于id nickname?在我看来,这有点反常。我希望您有一个id,那么那就是对象的标识,因此可以在相等条件下使用。

我还看到您有一个用户ID的设置器。那么,您真的要更改用户ID吗?我发现您可以更改昵称,这很有意义。但我希望ID保持不变。

还要注意,由于要覆盖equals(),因此还应该覆盖hashCode()

现在,如果hashCode()和equals()依赖于不可变字段(例如id),则hashCode()的结果将不会改变,如果将User放入哈希集合(例如HashMap)中,则以后再也不会丢失(这非常令人困惑)!

最后(!),我将保护构造函数和设置器免受空昵称(使它们抛出IllegalArgumentExceptions),然后使equals()之类的代码不必担心空昵称(除非'null'代表昵称)。我会对id做同样的事情,因为您将其作为Long(对象)。但这不是一个原始的时间吗?