Je concevons une simple application de discussion (juste pour le coup de pied). Je me suis demandé d'un design simple pour cette application de discussion. Pour vous donner une vue d'ensemble .. Voici les règles:
c'est ça! (Voir je vous ai dit que c'était une simple application de discussion). Donc, mon intention n'est pas vraiment la demande; Mais le modèle de conception et les objets utilisés. P>
Voici comment je l'ai conçu. (Je suis codé dans Java .. au cas où cela compte vraiment) p>
D'accord .. Donc, maintenant, j'ai mis en œuvre un modèle d'observateur en faisant de la mise en œuvre de Chatwindow "Chatlistener" Patter qui a une méthode appelée "notification (message)". Donc, la Chatsession notifie chaque chatwindow enregistré. P>
Maintenant voici quelques choses que je veux clarifier / vouloir votre opinion sur. 1. J'ai besoin d'avoir une méthode de désenregistrer également pour toutes les fenêtres de discussion, si une fenêtre de discussion est fermée et ne veut pas obtenir plus de notifications. Cela signifie potentiellement que, soit je devrais avoir un gestionnaire d'enregistrement central "statique" qui n'a qu'une instance, puis une fenêtre de discussion devrait pouvoir se désinscrire en fournissant une "session de discussion". Pour cette raison, chaque session de discussion devrait avoir un identifiant. (Inclus ici). Ou je pourrais maintenir une instance de chatsession dans la fenêtre de discussion aussi, pour toujours avoir une instance prête. (Je déteste les singletons comme je pense qu'ils vont contre oups). Une autre manière ne serait pas de ne pas avoir de contrôle de désenregistrement de la fenêtre de discussion, avec la fenêtre de discussion, la notification de la fermeture de la fenêtre doit plutôt venir directement à la discussion et qu'elle devrait faire, ce qu'il devrait faire! P>
Cette conception a du sens du tout? Si vous dites que c'est un morceau de merde et donnez-moi une approche encore meilleure; Vous obtiendrez certainement un grand merci de moi. Outre le modèle d'observateur, quels modèles pourraient être utilisés ici pour le simplifier plus ou le rendre meilleur. Aussi .. Tout point faible de cette conception, s'il est approprié mais peut être amélioré. P> li>
Aussi lorsque un utilisateur tape un nouveau message dans sa propre fenêtre de discussion; Il doit être propagé à toutes les fenêtres de discussion, quelle est la session de discussion, mais en même temps; Est-ce que cela signifie que la session de chat a-t-elle besoin d'obtenir un message avec "ID de la fenêtre de discussion" et message? Et puis il le propocine à toutes les fenêtres, y compris celui qui est le propriétaire du message? Qu'est-ce qu'un meilleur moyen de gérer cela. Je veux dire, une manière où la fenêtre permet à la session de discussion du message puis de discuter avec toutes les autres fenêtres. (Je pense que cela aura besoin de certains si ... ne les aime pas non plus) p>
Quoi qu'il en soit, laissez-moi savoir vos commentaires. Aussi s'il vous plaît rem. L'application de travail n'est pas l'intention, je suis à la recherche d'une bonne discussion, de bonnes pratiques de modèle de conception et d'utilisation. p> li> OL>
Code complet ci-dessous, si cela vous donne une grande ... N'hésitez pas à la déchirer et à modifier des problèmes liés à presque toutes les sémantiques. P>
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);
}
}
}
}
3 Réponses :
La conception de base semble-être pour moi. Évidemment, pour compléter cela, vous ne voudriez pas ajouter beaucoup plus de fonctionnalités. La conception actuelle conserve tous les messages en mémoire indéfiniment, mais à un moment donné, vous aurez besoin de code pour purger les anciens messages. P>
Les quelques problèmes de conception importants que je vois sont: p>
Ouais .. Je suis d'accord avec les deux points .. Toutefois .. Si vous le regardez, des messages peuvent même dire à quel utilisateur l'a envoyé et qu'aucun horodatage. L'envisageait de faire une implantation d'interface de message avec une classe IPL plus complète. Qui appendrait probablement l'horodatage et l'expéditeur. En ce qui concerne la persistant du message, oui qui a traversé mon esprit, mais je n'ai pas impliqué cette partie ou l'interface utilisateur, car je ne tente pas vraiment de développer la demande, mais seulement pour obtenir la conception de la conception pour le moment, pour des trucs de base. Plus d'apprentissage des modèles de conception. Cela étant dit, les commentaires sont très appréciés. Merci.
Je suggérerais d'examiner les frameworks de messagerie au lieu d'utiliser un motif d'observateur. P>
Jetez un coup d'œil à cette simple implémentation qui sera suffisante pour votre projet de jouet - eventbus ( plus disponible). Sinon, vous pouvez utiliser une implémentation complète JMS blown, comme Activemq . P>
Fondamentalement, il vous permet de définir un bus commun auquel vous pouvez enregistrer et désinscrire les participants et également envoyer des messages que tous les participants verront. Le grand avantage sur le modèle d'observateur est le très faible couplage entre les participants - vous ne vous enregistrez pas avec chaque objet pour obtenir ses messages - vous venez de vous inscrire une fois avec le bus. En outre, vous obtenez un traitement asynchrone - disons que vous avez 1000 sessions de discussion - si vous utilisez l'observateur, cela signifie que pour chaque message à remplir, il faudra pour mettre à jour 1000 sessions. Avec Message Framework Message Envoyer est très rapide et notifiant que toutes les 1000 sessions se font en arrière-plan. P>
Juste en regardant l'objet code> code>, pourquoi l'égalité dépend de l'identifiant et em> surnom? Cela me semble un peu intuitif pour moi. Je m'attendrais à ce que vous ayez une pièce d'identité, alors c'est l'identification de l'objet, et donc ce que vous utiliseriez dans une condition d'égalité. P>
Je vois aussi que vous avez un setter pour l'ID utilisateur. Alors voulez-vous vraiment changer d'ID utilisateur? Je vois que vous pouvez changer le surnom, ce qui a du sens. Mais je m'attendrais à ce que l'ID reste constant. p>
Notez également que, étant donné que vous remplissez égale (), vous devez également Maintenant, si HashCode () et Equals () comptez sur des champs immuables (par exemple, l'ID), les résultats de HASHCODE () ne changeront pas et si vous mettez un utilisateur dans une collection hachée (par exemple, HASHMAP) (par exemple, HASHMAP), puis. Vous n'allez pas la perdre plus tard (ce qui est très confus)! P>
Enfin (!) Je protégerais le constructeur et les configurateurs contre les surnoms nuls (faites-les jeter illégalargumentexceptions), puis le code comme des égaux () n'a pas à s'inquiéter d'un surnom nul (à moins que 'Null' ait une signification pour le surnom). Je ferais la même chose pour id, puisque vous l'avez aussi longue (objet). Mais cela ne pourrait-il pas être une primitive longue? P>
Merci beaucoup pour des commentaires précieux. C'est ce que je cherchais exactement. J'aurais accepté votre réponse comme droite, tout de suite; Mais j'attendrai un moment; au cas où les gens montent avec plus de réponses. :)
C'est très bien. Je ne me suis pas concentré sur le modèle global comme vous l'avez demandé, je suppose donc que d'autres réponses sont plus appropriées pour «acceptation», mais bien de savoir que ce qui précède est utile