2009-06-20 8 views
2

J'essaye de trouver un bon design pour convertir un ensemble d'objets différents en un objet commun. Fondamentalement, je reçois un objet complexe (de plusieurs légèrement différent) du système A, et dois le convertir en un objet plus simple pour le système B.Conception pour convertir des objets

Les objets dont je convertis tous héritent de la même classe de base, donc partie de la conversion est toujours le même. Mais dans tous les cas, la conversion implique quelque chose de très spécifique au type d'objet que je convertis. Cela peut être un RPC, un chargement HTTP, une recherche dans une base de données ou quelque chose de complètement différent. Je regarde les modèles Template method et Strategy. Mais ni l'un ni l'autre ne semble être un ajustement parfait. Le problème est que la méthode/stratégie à utiliser est liée au type d'objet converti et n'est donc pas interchangeable.

C'est une esquisse de ce que je pense à faire:

class FooConverter { 
    Map<String, FooConverter> converters; 
    Foo convert(Bar bar) { 
     Foo foo = ...; // Common part of the conversion. 
     FooConverter c = converters.get(bar.getType(), foo); 
     c.finishConversion(bar, foo); 
     return foo; 
    } 
} 

Ce qui me contrarie est que FooConverter doit définir une méthode de conversion supplémentaire qui prend l'objet partiellement converti en paramètre. Donc je me retrouve avec un mélange de stratégie (puisque tous les convertisseurs implémentent la même interface) et de méthode de template (puisque la partie commune de la conversion est partagée par tout le convertisseur). Y a-t-il un meilleur moyen?

Répondre

2

Il semble que vous ayez besoin de traverser une structure et de pouvoir faire quelque chose avec chaque élément de la structure. Ce 'quelque chose' varie selon le type de l'élément, et vous voulez aussi pouvoir faire varier comment ce 'quelque chose' est implémenté.

Si tel est le cas, cela ressemble à un ajustement parfait pour le modèle Visitor. Je l'ai récemment utilisé moi-même dans un scénario semblable au vôtre où j'avais besoin de convertir une structure en une autre de manière flexible.

+0

+1 Le motif du visiteur semble le mieux adapté ici. – skaffman

+0

Le modèle de visiteur semble être le chemin à parcourir, merci! Comme je ne peux pas modifier les classes du système A, j'aurai besoin d'une sorte de wrapper pour Bar, mais ça ne devrait pas être trop mauvais. – albertb

0

Vous pouvez implémenter une sous-classe du type cible avec un constructeur pour chacun des types donnés à partir desquels vous convertissez. À partir des constructeurs appelez le constructeur surchargé de son type parent.

Quelque chose comme:

public class ConvertedFoo extends Foo 
{ 
    public ConvertedFoo(SuperTypeA a) { 
     // Do some common stuff here. 
    } 

    public ConvertedFoo(SubtypeOfSuperTypeA a) { 
     ConvertedFoo((SuperTypeA)a); 
     // Do more specific stuff here. 
    } 
} 

Si la classe ConvertedFoo est trop grand, il peut facilement être fractionné sous-types. Ceci permettrait une réutilisation maximale du code et centraliserait tout votre code de conversion sans utiliser le contrôle de type dynamique.

Je ne pense pas que ce soit un modèle nommé. Si quelqu'un sait, j'aimerais connaître son nom.

+0

Cela semble bon. Mais je ne peux pas utiliser la classe pour déterminer la conversion dont j'ai besoin, j'ai vraiment besoin d'appeler 'getType()' pour déterminer le type de conversion nécessaire. – albertb

+0

Aussi, je préfère ne pas instancier un nouvel objet pour chaque conversion puisque j'ai des pools de connexions, etc. que je préfère ne pas rendre global. – albertb

+0

Pourquoi avez-vous besoin d'appeler getType? Appelez simplement le constructeur avec l'objet pour le convertir. À moins que vous ne convertissiez tous vos objets en collection ... –

2

Vous prenez un tas d'objets "Convertable", peut-être que vous pourriez faire "Foo" avoir des décorateurs pour chaque type de base "Convertable", lorsque vous détectez le type "Convertable", vous pouvez ajouter le décorateur approprié. Foo "?

1

Il y a au moins deux façons de le faire:

  1. Utilisez la méthode modèle. Cela a une méthode de conversion dans super classe (Bar) et l'implémenter dans les sous-classes (par exemple, MyBar, HttpBar etc). C'est bien tant que la classe sait comment se convertir. Vous pouvez avoir une méthode toFoo() dans Bar. Les sous-classes appellent super.toFoo() et font les choses nécessaires.
  2. La méthode ci-dessus peut ne pas être toujours souhaitable puisque conceptuellement la conversion n'est pas le travail de Bar. Dans ce cas, vous pouvez utiliser le modèle Visitor. Vous pouvez avoir une hiérarchie parallèle de classes de conversion. Chaque classe peut accepter un type particulier de barre et faire la conversion.
Questions connexes