Je traite avec un ensemble d'objets de message, chacun ayant un identifiant unique correspondant à celui-ci. Chaque message peut être construit à partir d'une carte ou d'un bytebuffer (les messages sont binaires, mais nous savons comment transférer vers et à partir d'une représentation binaire).
La mise en œuvre actuelle pour la construction de ces messages est approximativement comme suit: < / p> maintenant, Java de Josh Bloch < / a> Discussions sur le point 1: Considérez des méthodes d'usine statiques au lieu de constructeurs, ce qui semble être un lieu où ce modèle est utile (les clients n'accumulent pas directement les constructeurs des sous-types de message; au lieu de cela, ils traversent cette méthode). Mais je n'aime pas le fait que nous devions nous rappeler de conserver deux déclarations de commutation mises à jour (enfreint le Dry < / a> principe). P> J'apprécierais tout aperçu de la meilleure façon de l'accomplir; Nous ne mettrions pas des objets de mise en cache (chaque appel à FRTMAP ou de FROMBYTEBuffer retournera un nouvel objet), ce qui annule certains des avantages de l'utilisation d'une méthode d'usine statique comme celle-ci. Quelque chose à propos de ce code me frappe comme mal, alors j'aimerais bien entendre la pensée de la communauté sur le fait qu'il s'agisse d'un moyen valide de construire de nouveaux objets, ou sinon quelle solution serait une meilleure solution. P> P>
9 Réponses :
Peut-être que vous pourriez créer une interface message de mise en œuvre et des implémentations: Suivant, une méthode getfactoryfromid dans la même classe que les méthodes ci-dessus: p> Cependant, au lieu de cela, il est préférable de créer un hashmap contenant les identifiants et les usines, vous n'avez donc pas à créer un nouvel objet d'usine chaque fois que vous créez un message. Voir aussi le Commentaire ci-dessous . P> et vos méthodes: p> De cette façon, vous utilisez le motif d'usine et il n'est pas nécessaire d'avoir deux fois la même instruction de commutation. P> (n'a pas testé cela, donc éventuellement certaines erreurs de compilation / fautes de frappe) p> p>
Si les objets d'usine sont stockés sur une carte et récupérés par UUID, aucun interrupteur n'est nécessaire.
Yup, c'est ce que j'ai dit :-) J'ai même ajouté un lien à votre réponse :)
C'est une bonne solution (donc +1 pour cela), mais si l'objectif était de se débarrasser de la double commutation, vous auriez pu simplement surmonter la logique de commutation à une méthode distincte. (La carte est essentiellement un changement de déguisement)
Vous pouvez utiliser le modèle abstractfactory code>, où vous auriez une classe d'usine pour chaque type de message, qui vous renvoie le message par tampon ou par carte. Vous créez ensuite une méthode qui vous renvoie l'objet d'usine correspondant. De l'usine renvoyée, vous créez ensuite le message. P>
Y a-t-il un moyen de convertir le bytebuffer en une carte ou autre chose? Ce serait bien si vous convertissez l'entrée en forme normalisée et appliquez un interrupteur unique. P>
Si ce que vous voulez faire est d'obtenir un message et de le formater avec des valeurs spécifiques (comme "la table: Tableau n'a pas de colonne nommée: Colname") Vous pouvez convertir le byTEbuffer en une carte et appeler la première méthode . Si vous avez besoin d'un nouveau msgstr, vous n'étendez que la méthode FRTMAP. P>
C'est quelque chose comme affacter la partie commune. p>
Si vous avez vos objets implémenter une interface déclarant des méthodes d'usine tels que: dans une classe imbriquée statique, votre usine peut créer une carte code> contenant des objets d'usine indexés par l'UUID: p> et remplacez vos commutateurs par la carte de la carte: p> public static Message fromMap(int uuid, Map<String, Object> fields) {
Factory fact = map.get(Integer.valueOf(uuid));
return (null == fact) ? null : fact.newInstance(fields);
}
public static Message fromByteBuffer(int uuid, ByteBuffer buffer) {
Factory fact = map.get(Integer.valueOf(uuid));
return (null == fact) ? null : fact.newInstance(buffer);
}
Juste un petit commentaire: vous devriez utiliser Integer.Valueof () plutôt que neuf entier ().
Je recommande d'utiliser un type Enum avec des méthodes abstraits, telles que l'exemple suivant: de cette façon, dans vos méthodes statiques existantes, vous pouvez simplement faire cela ... P> Cette approche enregistre votre méthode statique de devoir connaître les messagetypes que vous prenez en charge et comment les construire - vous pouvez ajouter, modifier ou supprimer des messages sans refactoring les méthodes statiques. p> p>
Vous devez abstrumer votre puis le mettre en cache dans votre usine (par opposition à un commutateur): p> firstMessage code> objet:
public static Message fromMap(UUID uuid, Map<String, Object> fields) {
return MESSAGES.get(uuid).newInstance();
}
Vous pouvez modifier le message de sorte qu'il dispose de deux méthodes d'initialisation, une pour la carte et une pour BYTEBUFFER (au lieu des deux versions de rétroducteur). Ensuite, votre méthode d'usine renvoie le message construit (mais non inijiorialisé), puis vous appelez Initialiser avec la carte ou la bytebuffer sur l'objet renvoyé.
Vous avez maintenant une méthode d'usine comme celle-ci: - P>
public static Message fromByteBuffer(int uuid, ByteBuffer buffer) { Message message = createMessage(uuid); // TODO: null checking etc.... return message.initialize(buffer); }
TEM 1: Considérez des méthodes d'usine statiques au lieu de constructeurs em> p>
Vous faites déjà cela en cachant le constructeur derrière cette méthode d'usine, il n'est donc pas nécessaire d'ajouter une autre méthode d'usine ici. p>
Vous pouvez donc le faire avec une interface d'usine et une carte. (Fondamentalement, ce que tout le monde dit déjà, mais avec la différence, que vous pouvez aligner les usines à l'aide de classes intérieures) p>
xxx pré> et vos invocations se transformeront en: p> < Pré> xxx pré>
car l'UUID utilisé pour le commutateur est utilisé comme clé pour les usines. P> blockQuote>
À propos de la solution à l'aide de l'ENUM en tant que stratégie (ajouter des méthodes stratégiques à un ENum) L'application de feuille de cheet de code de nettoyage indique qu'il s'agit d'un tueur de maintenabilité.
Bien que je ne sache pas pourquoi je voudrais partager cela avec vous. P>
Intéressant. Mais s'il vous plaît ajouter des commentaires comme ceux-ci comme des commentaires plutôt que des réponses.