适用于简单聊天应用程序的设计模式
我正在设计一个简单的聊天应用程序(仅供参考)。我一直在想这个聊天应用程序的简单设计。给你概述..这里是规则:适用于简单聊天应用程序的设计模式
- 匿名用户输入聊天只是一个绰号。 (用户ID)大概由系统在后台分配。
- 他们可以加入(订阅)聊天对话。他会看到来自其他用户的聊天文本出现在指定区域。
- 他们可以回复特定的对话,其他人都可以看到该对话。
这样! (看我告诉你这是一个简单的聊天应用程序)。所以,我的意图不是真正的应用程序;但其中使用的设计模式和对象。
现在这里是我设计它的方式。 (我编码在java中。在真正重要的情况下)
- 用户对象 - 两个属性ID和昵称
- 消息对象 - 一个简单的信息接口和实现(现在)作为SimpleMessage中,有字符串作为包含消息的属性。
- 聊天窗口对象 - 用户和消息的基本组成。因为它有一个用户对象和消息列表。
- 聊天会话 - 再次组成。基本上它会有一个聊天窗口列表。每个聊天窗口注册到聊天会话。聊天会话负责在出现新消息时通知所有聊天窗口。 (Observer模式的人?)
好了..所以现在我已经实现观察者模式通过使ChatWindow实施“ChatListener”拍打它有方法被称为“通知(消息)”。所以ChatSession通知每个已注册的ChatWindow。
现在,这里有几件事情我想澄清/希望你的意见。 1.如果聊天窗口关闭并且不想再收到任何通知,我还需要为所有聊天窗口注销注册方法。这可能意味着,要么我应该有一个只有一个实例的“静态”中央注册管理器,然后任何聊天窗口都应该能够通过提供“聊天会话”ID来注销自己。出于这个原因,每个聊天会话都应该有一个ID。 (包括在内)。或者我也可以在聊天窗口中维护ChatSession的一个实例,以便始终准备好一个实例。 (我讨厌单身人士,因为我认为他们反对哎呀)。 另一种方法是不使用聊天窗口取消注册聊天窗口控制,而是关闭窗口通知应该直接发送到ChatSession,并且它应该做,它应该做什么!
这种设计是否有意义?如果你认为这是一个CRAP,并给我一个更好的方法;你一定会从我这里得到一个很大的谢意。除了观察者模式之外,所有模式都可以在这里用来简化它或者使其更好。此外,这个设计的任何弱点,如果它是适当的,但可以改善。
-
此外,当用户在他自己的聊天窗口中输入新消息时,它需要传播到所有聊天窗口,这是聊天会话所做的,但同时;这是否意味着..聊天会话需要通过“聊天窗口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);
}
}
}
}
感谢所有贡献者提前。 干杯
只看User
对象,为什么相等取决于ID 和昵称?这对我来说似乎有点不直观。我期望如果你有一个id,那么这就是对象的标识,因此你在平等条件下使用什么。
我还看到你有一个用户id的setter。那么你真的想改变用户ID吗?我看到你可以改变昵称,这是有道理的。但我希望这个id保持不变。
还请注意,由于您重写equals(),您还应该override hashCode()。现在,如果hashCode()和equals()依赖于不可变字段(例如id),那么hashCode()的结果将不会改变,并且如果将用户放置在哈希集合中(例如HashMap)那么你以后就不会失去它了(这很混乱)!(),我会保护构造函数和setter对空的昵称(使它们抛出IllegalArgumentExceptions),然后像equals()这样的代码不必担心空昵称(除非'null'具有昵称)。我会为id做同样的事情,因为你将它作为Long(对象)。但这不可能是一个原始的长期?
基本的设计看起来很健康。很显然,要完成这一点,你需要添加更多的功能。目前的设计将所有消息无限期地保存在内存中,但在某些时候,您将需要用于清除旧消息的代码。
的几个显著的设计问题,我确实看到有:
- 消息接口没有链接回邮件的发送者 - 大多数的聊天记录显示谁说什么,这将是困难的无消息中的用户字段。
- 消息接口没有时间属性。这将使清除旧邮件更加困难。
是的..我同意这两点..然而..如果你看看它,目前的消息甚至可以告诉哪个用户发送它,没有时间戳。正计划用一个更全面的impl类为Message接口实现一个impl。这可能会附加时间戳和发件人。 至于坚持这个信息,是的,但我并没有实现这个部分或用户界面,因为我真的没有试图开发应用程序,而只是为了获得现在的设计,对于基本的东东。更多的是设计模式的学习。 这就是说,评论非常感谢。谢谢。 – Priyank 2009-07-29 04:29:04
我建议调查消息框架而不是使用Observer模式。
看看这个简单的实现,这将足以为您的玩具项目 - eventbus(不再可用)。或者,您可以使用完全成熟的JMS实现,如ActiveMQ。
基本上它允许你定义一个公共总线,你可以注册和取消注册参与者,也可以发送所有参与者都会看到的消息。与观察者模式相比,最大的优势是参与者之间的耦合度非常低 - 您不需要向每个对象注册以获取他的消息 - 您只需在公交车上注册一次。此外,您还可以进行异步处理 - 假设您有1000个聊天会话 - 如果您使用观察者,则意味着要完成每条消息,将需要更新1000个会话。使用消息框架消息发送非常快,并且通知所有1000个会话在后台完成。
非常感谢您的宝贵意见。这正是我正在寻找的东西。我会马上接受你的答案,但我会等一会儿;以防人们想出更多答案。 :) – Priyank 2009-07-29 10:53:56