2008-09-24 17 views
2

Je développe un petit éditeur de classe UML en Java, principalement un projet personnel, il pourrait finir sur SourceForge si je trouve le temps de créer un projet dessus.Mauvais problème de conception OO - J'ai besoin d'une fonctionnalité générale en Java mais je ne sais pas comment l'implémenter

Le projet est bien avancé: je peux créer des classes, les déplacer, créer des interfaces, créer des liens, etc.

Qu'est-ce que je travaille sur est la boîte de dialogue pour définir les propriétés de classe/interface et la création de nouvelles classes/interfaces.

Par exemple, j'ai une classe qui étend JDialog. C'est la "fenêtre" principale pour éditer les classes et les interfaces (enfin, il y a une classe pour chacun). Il contient un JTabbedPane qui à son tour contient JPanels.

Ce JPanel sont en fait ceux personnalisés. J'ai créé une classe abstraite qui étend JPanel. Cette classe utilise des composants (définis par ses sous-classes) et ajoute leurs valeurs à un JTable (également contenu dans le JPanel). Par exemple, si je veux modifier les attributs d'une classe, le JPanel contiendra un JTextField pour entrer le nom de l'attribut ainsi qu'un autre pour entrer son type. Il y a aussi un ensemble de boutons pour traiter les données entrées dans ces champs. Lorsque je clique sur "Enregistrer", les données que j'ai entrées dans JTextFields sont ajoutées dans le JTable (à la Enterprise Architect). La classe concrétisée qui étend l'abstraction est responsable de la définition du contrôle et de la décision de faire quoi avec les données lorsqu'une ligne est ajoutée ou supprimée de la JTable. La gestion de JTable est, cependant, la responsabilité de la classe abstraite.

Voici mon problème: dans OO, une classe a des méthodes, et une interface a aussi des méthodes. Je me suis dit: je pourrais utiliser le même JPanel personnalisé en béton (AttributesPanel (qui étend la classe abstraite JPanel que j'ai créée)) pour stocker les méthodes pour une classe ou une interface.

Cependant, la classe doit conserver une copie (en tant qu'attribut) de la classe ou de l'interface sur laquelle je travaille. De cette façon, quand une méthode est ajoutée, je peux appeler editClass.addMethod() (ou editInterface.addMethod()). Le problème est que je n'ai aucun moyen de dire si je travaille sur un Class ou un Interface.

La solution que j'ai trouvée est laide: conserver un attribut editedClass et un attribut editedInterface dans la classe AttributesPanel. Selon que je modifie une classe ou une interface, l'un de ces attributs sera nul alors que d'autres ne le seront pas.

Il est assez moche si vous me demandez. En fait, je peux entendre mes professeurs de génie logiciel dans ma tête hurler d'agonie tout en brûlant (enfin, en fait, en train de geler) dans le neuvième cercle de l'Enfer.

Le moyen rapide de résoudre ce problème de conception serait de créer une interface appelée "ObjectWithMethods", que mes classes Class et Interface implémenteront. De cette façon, je n'aurai qu'à mettre un paramètre ObjectWithMethods dans ma classe AttributesPanel. Mais est-ce que cela signifie que je devrais créer une classe nommée "ObjectWithAttributes", ou "ObjectWithBlahBlah"? Je vois un bon potentiel "The Daily WTF" ici ... D'ailleurs, je ne pense pas que je devrais modifier mes objets de domaine (une classe, interface, note, relation (pour mon éditeur UML)) ou créer une nouvelle interface juste pour le bien de certaines considérations d'assurance-chômage ....

Qu'en pensez-vous?

Vous avez besoin de plus de précisions (parce que je suis très fatigué en ce moment et j'ai tendance à mal me tromper (surtout en anglais - ma langue maternelle est le français) alors que dans cet état d'esprit ... Je vais éditer cette question.

Cheers,

Guillaume.

Répondre

3

Lorsque j'ai lu votre question, il semble vraiment que vous décrivez un endroit pour utiliser le visitor pattern.

La raison pour laquelle le modèle de visiteur devrait fonctionner ici est une idée connue sous le nom de double expédition. Votre code d'interface utilisateur fera un appel et passera une référence à lui-même, puis la classe ou l'interface finira par appeler l'appelant d'origine. Puisque la classe ou l'interface est celle qui appelle la méthode, elle connaît son propre type et comment faire le travail spécifique à son type.

Bien sûr, ma description est insuffisante pour implémenter cette technique, donc vous aurez envie de lire dessus. Je pense que c'est bien documenté. Par exemple, j'ai trouvé cela en environ 2 secondes en Java qui devrait vous aider à démarrer: http://www.javaworld.com/javaworld/javatips/jw-javatip98.html

0

Habituellement, je fais juste la chose la plus simple, et commence à penser à factoriser les interfaces, quand je commence à voir trop de if(.. instanceof ..) - aime construire dans mon code. Cela ne me coûte pas beaucoup avec les capacités modernes de refactorisation de code IDE.

Dans votre cas spécifique, je considérerais l'implémentation des diagrammes fournis dans UML specification, parce qu'ils étaient si gentils de spécifier UML en utilisant la notation UML!

0

Vous avez une application. Dans cette application. votre représentant, et éditez quelques données. Ces données représentent une classe de langage de programmation ou une interface de langage de programmation. Lorsque vous créez un éditeur pour certaines données, vous devez parfois ajouter des informations supplémentaires/complémentaires. Par exemple, chaque graphique de classe peut avoir une couleur de ligne différente et n'a rien à voir avec les attributs ou les méthodes de ta classe.

Il en va de même pour le champ ou la propriété qui indique si vous modifiez une classe ou une interface.

Je suggère de faire certaines choses.

Séparer les données représentées à partir du code ou la logique de votre programme:

si vous avez quelque chose comme:

// all code, classes, mixed up 
public class JCustomPanel: { 

    protected ChartClass Charts; 
    protected ArrayList<String> MyClassAttributes; 
    protected ArrayList<String> MyClassMethods; 

    void PanelDoSomeThing(); 
    void ClassDoSomeThing(); 
    void InterfaceDoSomeThing(); 

    // ... 
} // class JCustomPanel 

Changement à ceci:

// things related to a single class or interface, 
// nothing to do with the chart 

public class JClassRepresentation: { 

    ArrayList<String> Attributes; 
    ArrayList<String> Methods; 

    bool IsInterface; 

    void ClassDoSomeThing(); 
    void InterfaceDoSomeThing(); 

    // ... 
} // class JCustomPanel 

// things related to the editor, 
// contains the classes and interfaces, 
// but, as separate stuff 
public class JCustomPanel: { 

    ArrayList<JClassRepresentation> Classes; 

    int PagesCount; 

    void InterfaceDoSomeThing(); 

    // ... 
} // class JCustomPanel 

Vive.