2013-10-16 2 views
0

Je tente de concevoir un serveur de traduction. Il existe une classe POJO (RootClass) dans mes systèmes locaux. et il y a aussi un système distant pour envoyer un objet distant (RemoteClass) à mon système. La responsabilité de ce service est de traduire la classe Remote en classe Root. Le problème est que: Il y a tellement de types. par exemple. plus de 200 types. J'ai besoin d'écrire if-else énorme pour faire cette traduction:Conception pour la couche de traduction

Je liste un code de pseudo-code pour décrire cette question.

public class RootClass { 
    public String type; 
    public String attr1; 
    public String attr2; 
    public String attr3; 
    public String attr4; 
} 


public class RemoteClass { 
    public String type; 
    public String attr1; 
    public String attr2; 
    public String attr3; 
} 


public class Translator{ 

    public RootClass translate(RemoteClass remote) { 
     RootClass root = new RootClass(); 

     if ("a".equals(remote.type)) { 
      root.type = "veryGood"; 
      if ("one".equals(remote.attr1)) { 
        root.attr2 = "true"; 
      } 
      if ("two".equals(remote.attr1)) { 
       root.attr3 = "true"; 
      } 
      if ("1".equals(remote.attr1) && "2".equals(remote.attr2)) { 
       root.attr4 ="good"; 
      } 

     } else if ("b".equals(remote.type)) { 
      root.type = "good"; 
      if ("one".equals(remote.attr1)) { 
       root.attr2 = "1"; 
      } else if ("two".equals(remote.attr1)) { 
       root.attr2 ="2"; 
      } 

     } else if ("c".equals(remote.type)) { 
      root.type = "good"; 
      if (remote.attr2.indexOf(":") > 0) { 
       String[] strArray = remote.attr2.split(":"); 
       root.attr2=strArray[0]; 
       root.attr3=strArray[1]; 
      } 

     } 

    } 
} 

Les 2 objets décrivent 1 chose avec une structure totalement différente. La classe racine est le noyau de notre système et impossible à paver et nous pensons également que cette classe Racine est très appropriée pour le système local. et pour la classe à distance provient de systèmes tiers que nous n'avons pas la permission de modifier. Donc, cette traduction est devenue très difficile.

Ce que je prévois de supprimer est de créer plus de 200 adopteur pour la traduction: par exemple:

public class adopterA implements RootAdoper { 
public RootClass translate(RemoteClass remote) { 
    RootClass root = new RootClass(); 
    root.type="veryGood"; 
    if ("one".equals(remote.attr1)) { 
     root.attr2 = "true"; 
    } 
    if ("two".equals(remote.attr1)) { 
     root.attr3 = "true"; 
    } 
    if ("1".equals(remote.attr1) && "2".equals(remote.attr2)) { 
     root.attr4 ="good"; 
    } 
} 

}

Et mettre tous ceux dans HasMap

Map<String, RootAdoper> map = new HashMap<String, RootAdoper>(); 

Mais encore ont 200 petite classe à emballer si/autrement, Est-ce que n'importe quel bon modèle ou conception pour résoudre ce problème complexe? Merci d'avance.

Répondre

1

Quelle est la clé de votre carte? si la clé est le Remote.type alors vous pouvez juste faire

rootClass = map.get(remote.type).translate(remote); 

Ce qui ne se débarrasse du if/else si les blocs. Veillez simplement à gérer les régions inconnues/non traduites ou ayez un NullObject qui ne traduit pas ou n'effectue pas de traduction par défaut.

Le nom technique de ce livre du refactoring pour modèles est appelé « Remplacer conditionnel Dispatcher avec la commande »

Il vous reste à remplir la carte bien. Peut-être une façon de le faire est de faire toute l'interface RootAdoper une énumération et toutes les implémentations les types dans l'énumération. Vous pouvez également ajouter une nouvelle méthode à l'énumération pour obtenir le Remote.Type que chaque valeur peut traduire.

enum RootAdoper{ 

    A{ 
     @Overide 
     public RootClass translate(RemoteClass remote){ 
      //... 
     } 

     @Override 
     public String getTypeToTranslate(){ 
      return "A"; 
     } 
    }, 
    ... // other types listed here similarly 
    ; 

    abstract RootClass translate(RemoteClass remote); 

    abstract String getTypeToTranslate(); 
} 

Ensuite, vous pouvez remplir la carte comme cette

Map<String, RootAdoper> map = new HashMap<String, RootAdoper>(); 

for(RootAdoper adoper : RootAdoper.values(){ 
     map.put(adoper.getTypeToTranslate(), adoper); 
} 
+0

Merci. Ce serait mieux quand utiliser enum. Bonne idée. Mais cette énumération est encore grande. Est-il possible de faire tout cela en configuration? J'ai généralement toutes ces informations de l'expert du domaine. Je recueille ces informations pour exceller et ensuite je travaille sur le code. Est-ce possible d'avoir tout cela en configuration, cela va réduire beaucoup de travail. Je veux dire: A: VeryGood. B: bien. C'est facile à configurer dans la base de données ou le code source. mais pour d'autres règles complexes '(remote.attr2.indexOf (": "))' est très difficile à faire de cette façon. Vous êtes très bon à refactor, Alors pouvez-vous me donner une suggestion à ce sujet. – Bensson

+0

Les classes codées ou générées dynamiquement en lisant un fichier DB ou Excel sont toutes deux de bonnes options. Je préférerais l'un à l'autre en fonction de la fréquence à laquelle les règles de traduction changent.Si les règles ne changeront jamais ou changeront si rarement que n'importe quel changement exigerait la réécriture du code, je dirais aller pour la méthode que je décris ci-dessus. Vous avez seulement la peine d'écrire le code une fois et ensuite cela fonctionnera. Lire DB ou config/excel est plus compliqué, car cela nécessite un traducteur de plus pour analyser la configuration et vous obtiendrez encore beaucoup de classes – dkatzel

+0

Merci pour votre réponse. – Bensson

Questions connexes