2016-10-07 2 views
0

J'implémente le frontend d'une application dans GWT (voir image ci-jointe) et j'ai une classe view qui s'agrandit à mesure que de nouveaux widgets sont ajoutés au frontend. enter image description here Comme indiqué dans le tutoriel GWT, la classe view doit implémenter l'interface Display de la classe de présentation. Le problème est que j'ai beaucoup de méthodes dans cette interface et que je les implémente dans la classe de vue, cela devient trop grand. C'est pourquoi je voudrais refactoriser le code pour réduire la taille de la classe de vue en implémentant ces méthodes dans d'autres classes et les référencer si nécessaire dans la classe view, par exemple en les regroupant par boîte de groupe (une classe par boîte de groupe) . Ci-dessous un exemple de code: Notez que dans l'application réelle, nous avons plus de widgets par boîte de groupe. Le problème auquel je suis confronté sera bien expliqué au fur et à mesure que vous lirez tout le message, car j'ajouterai plus de détails.Refactorisation d'une classe implémentant une interface en créant des sous-classes dans GWT/java

Code

à refactorisé:

ContactPrewsenter.java

public class ContactPresenter { 

public interface Display 
{ 
    void methodA(); 
    void methodB(); 
    void methodC(); 
    void methodD(); 
    void methodE(); 
    void methodF(); 
    . 
    . 
    . 
    void methodM(); 
} 

public ContactPresenter() 
{ 
    //Some stuff here 
} 
...... 
...... 

@Override 
public void bind(){ 
     //Some stuff here 
    } 

} 

ContactView.java:

public class ContactView implements ContactPresenter.Display 
{ 
    private final Listbox listBoxA; 
    private final Listbox listBoxB; 
    private final Listbox listBoxC; 
    private final Listbox listBoxD; 
    private final Listbox listBoxE; 
    private final Listbox listBoxF; 
    private final Listbox listBoxG; 
    private final Listbox listBoxH; 
    private final Listbox listBoxI; 
    private final Listbox listBoxJ; 
    private final Listbox listBoxK; 
    private final Listbox listBoxL; 
    private final Listbox listBoxM; 

    public ContactView() 
    { 

     listBoxA = new ListBox(); 
     listBoxB = new ListBox(); 

     VerticalPanel vPanel1= new VerticalPanel(); 
     vPanel1.add(listBoxA); 
     vPanel1.add(listBoxB); 

     GrooupBox groupBox1 = new GroupBox(); 
     groupBox1.add(vPanel1); 


     listBoxC = new ListBox(); 
     listBoxD = new ListBox(); 

     VerticalPanel vPanel2 = new VerticalPanel(); 
     vPanel2.add(listBoxC); 
     vPanel2.add(listBoxD); 

     GrooupBox groupBox2 = new GroupBox(); 
     groupBox2.add(vPanel2); 


     listBoxE = new ListBox(); 
     listBoxF = new ListBox(); 

     VerticalPanel vPanel3 = new VerticalPanel(); 
     vPanel3.add(listBoxE); 
     vPanel3.add(listBoxF); 

     GrooupBox groupBox3 = new GroupBox(); 
     groupBox3.add(vPanel3); 


     listBoxE = new ListBox(); 
     listBoxF = new ListBox(); 

     VerticalPanel vPanel4 = new VerticalPanel(); 
     vPanel4.add(ListBoxE); 
     vPanel4.add(ListBoxF); 
     .... 

     GrooupBox groupBox3 = new GroupBox(); 
     groupBox3.add(vPanel4); 



     listBoxG = new ListBox(); 
     listBoxH = new ListBox(); 
     .... 

     VerticalPanel vPanel = new VerticalPanel(); 
     vPanel.add(ListBoxG); 
     vPanel.add(ListBoxH); 
     .... 

     GrooupBox groupBox4 = new GroupBox(); 
     groupBox4.add(vPanel); 

     ...... 
     //create Horizontal/vertical panels, docklayout panel as well, to position the group boxes on the gui 
     .... 

    } 

    @Override 
    void methodA(){ 
     //uses listBoxA 
    } 

    @Override 
    void methodB(){ 
     //used listBoxB 
    } 

    @Override 
    void methodC(){ 
     //uses listBoxC 
    } 

    @Override 
    void methodD(){ 
     //uses listBoxD 
    } 

    @Override 
    void methodE(){ 
     //uses listBoxE 
    } 

    @Override 
    void methodF(){ 
     //uses listBoxF 
    } 

    @Override 
    void methodG(){ 
     //uses listBoxG 
    } 

    @Override 
    void methodH(){ 
     //uses listBoxH 
    } 

    . 
    . 
    . 

    @Override 
    void methodM(){ 
     //uses listBoxM 
     } 


    } 

J'ai essayé comme suit:

ContactPreseter.java

public class ContactPresenter 
{ 
    public interface Display extends groupBox1View.Display, groupBox2View.Display, groupBox3View.Display, groupBox4View.Display 
    { 

    } 
} 

classes preseter de chaque zone de groupe

public class groupBox1Presenter 
{ 
    public interface Display 
    { 
     void methodA(); 
     void methodB(); 
    } 
} 

public class groupBox2Presenter 
{ 
    public interface Display 
    { 
     void methodC(); 
     void methodD(); 
    } 
} 


public class groupBox3Presenter 
{ 
    public interface Display 
    { 
     void methodE(); 
     void methodF(); 
    } 
} 


public class groupBox4Presenter 
{ 
    public interface Display 
    { 
     void methodG(); 
     void methodH(); 
    } 
} 

ContactView.java

public abstract class ContactView implements ContactPresenter.Display 
{ 
    // adds group boxes to horizontal/vertical panels, and docklayout panel 
} 

Voici les classes d'affichage pour chaque zone de groupe:

Mais ici, j'éclipse me force à mettre en œuvre tous les méthodes de l'interface ContactPresenter.Display dans chacune de ces classes alors que, je voulais que ce soit la façon dont vous voyez implémenté ici.

Je me demandais s'il y avait un moyen de jouer avec les modificateurs d'accès pour y parvenir? Si non, s'il vous plaît je voudrais vous aider avec des idées comment le faire?

public groupBox1View extends ContactView implements groupBox1Presenter 
{ 
    public groupBox1View() 
    { 

    } 

    @Override 
    void methodA(){ 
     //uses listBoxA 
    } 

    @Override 
    void methodB(){ 
     //used listBoxB 
    } 
} 

public groupBox2View extends ContactView implements groupBox2Presenter 
{ 
    public groupBox2View() 
    { 

    } 

    @Override 
    void methodC(){ 
     //uses listBoxC 
    } 

    @Override 
    void methodD(){ 
     //used listBoxD 
    } 
} 

public groupBox3View extends ContactView implements groupBox3Presenter 
{ 
    public groupBox3View() 
    { 

    } 

    @Override 
    void methodE(){ 
     //uses listBoxE 
    } 

    @Override 
    void methodF(){ 
     //used listBoxF 
    } 
} 


public groupBox4View extends ContactView implements groupBox4Presenter 
{ 
    public groupBox4View() 
    { 

    } 

    @Override 
    void methodG(){ 
     //uses listBoxG 
    } 

    @Override 
    void methodH(){ 
     //used listBoxH 
    } 
} 

Répondre

0

Vous avez raison, votre vue devient trop grande. Vous devez le découper en composants qui traitent leurs propres problèmes.

Le framework d'édition s'avérera utile mais a ses propres limites. En fin de compte, vous avez un présentateur, travaillant avec le tout, mais ne lisant et n'écrivant qu'un seul objet de contact.

Vous construisez votre vue à partir de plusieurs composants, chacun peut avoir son propre présentateur et est responsable d'une partie de votre grand objet contact.

Un exemple: Au lieu d'exécuter 10 listes de type générique, créez 10 composants sémantiquement différents, responsables de la sélection de différents types de données: AgeListBox, CityListBox, FooListBox, BarListBox. Cela sépare le provisionnement des données pour les boîtes de votre présentateur central et dans les présentateurs spécifiques pour chaque zone de liste.

Démarrer au plus bas niveau et de combiner des vues d'édition pour chaque unité sémantique et les combiner à des objets plus grands de retour:

NameEditor, AgeEditor, FooEditor, BarEditor sont combinés en un AddressEditor, qui assemble avec un CVEditor en quelque chose de plus grand jusqu'à ce que vous arriviez finalement au niveau de contact.

J'espère que cela a du sens pour vous.

UPdate: Vous avez demandé le code, nous allons essayer quelques pseudocode:

Disons que vous avez un profil que vous souhaitez modifier. Il contient des

  • données personnelles
    • contient l'adresse de l'utilisateur
    • un tas d'adresses e-mail ou mobile
    • une image ou d'une connexion à gravatar
    • informations de paiement de l'utilisateur
  • la liste des tags qui vous intéressent
  • la liste des canaux il souscrivit
  • Newsletter/informations marketing
public class UserProfile { 
    PersonalData person; 
    List<NewsTopic> topicsOfInterest; 
    List<NewsChannel> subscriptions; 
    MarketingInfo marketingInfo; 

    // bean stuff, constr, equals etc. 
} 

public class PersonalData { 
    String name; 
    String firstName; 
    List<ContactDevice>phoneAndMailList; 
    ImageContainer userImage; 
    BankAccount paymentData; 
} 

Vous avez l'idée, je suppose ...

Vous pouvez maintenant écrire une classe de vue, détaillant toutes les informations que vous voyez ici, résultant en une vue de monstre monolitique et le présentateur de monstre correspondant. Ou vous suivez les conseils du gwtproject et découpez la vue en petits morceaux (composants). C'est-à-dire, les sous-vues et les présentateurs qui forment une hiérarchie, correspondant à celui de votre classe UserProfile. C'est essentiellement ce que le cadre de l'éditeur est vraiment bon. Dans l'éditeur fw, les vues sont appelées "Editors" (elles ont un sens), et elles sont alimentées par les données de l'éditeur principal dans la plus petite partie par une classe EditorDriver. GWT va générer la plupart du code pour vous, ce qui est très cool, mais ne fonctionne pas aussi parfait, si vous avez des parties optionnelles dans le profil.

Si nous appliquerions nous-mêmes, vous allez construire une structure comme celle-ci (j'évite l ' « Editeur » et remplacé par « Dialog »):

public class UserProfileDialogView extends Component implements HasValue<UserProfile> { 
    // subviews 
    @UiField 
    PersonalDataDialog personDataDlg; 
    @UiField 
    UserTopicListDialog topicListDlg; 
    @UiField 
    SubscriptionListDialog subscriptionListDlg; 
    @UiField 
    MarketingInfoDialog marketingInfoDlg; 

    @Overwrite 
    public UserProfile getValue() { 
     // we do not need to copy back the data from the sub-dialogs, because we gave them the values from the profile itself. 
     // Beware, substructures cannot be null in such a case! 
     return userProfile; 
    } 

    @Ovewrite 
    public void setValue(UserProfile profile) { 
     this.userProfile = profile; 
     // option one: manually distribute the profile parts 
     personDataDlg.getPresenter().setValue(profile.getPerson()); 
     topicListDlg.getPresenter().setValue(profile.getTopicsOfInterest()); 
     subscriptionListDlg.getPresenter().setValue(profile.getSubscriptions()); 
     // option two: use eventbus and valuechanged event, dialogs are 
    } 
} 

Il y a maintenant une variance de préoccupations: Qui définira la valeur dans les sous-boîtes de dialogue. Vous pouvez transmettre au présentateur de la sous-boîte de dialogue, ou vous le définissez directement dans la sous-boîte de dialogue. Quoi qu'il en soit, ce qui devrait vous éclairer maintenant, c'est que vous n'avez pas un seul présentateur pour diriger toutes les parties de la vue. Vous devez diviser les présentateurs pour être responsable d'une sous-vue chacun. Ce que j'ai trouvé utile dans un tel arbre de dialogue, était d'avoir une classe de modèle séparée, qui maintient l'objet en cours de modification et fournit une logique de communication de changement pour d'autres boîtes de dialogue.Par exemple, si vous ajoutez une liste de rubriques et si vous ajoutez un sujet, la boîte de dialogue de la sélection d'abonnement de chaîne peut vouloir savoir qu'il existe désormais un autre sujet à afficher dans le filtre de rubrique.

+0

Merci pour votre réponse. Je ne suis pas sûr de bien comprendre ce que vous voulez dire. Pourriez-vous s'il vous plaît écrire un exemple de code pour m'aider à mieux le comprendre? Ça me plairait vraiment :) –