Problema di progettazione OO errato: ho bisogno di alcune funzionalità generali in Java ma non so come implementarlo

StackOverflow https://stackoverflow.com/questions/125463

  •  02-07-2019
  •  | 
  •  

Domanda

Sto sviluppando un piccolo editor di classe UML in Java, principalmente un progetto personale, potrebbe finire su SourceForge se trovo il tempo di creare un progetto su di esso.

Il progetto è piuttosto avanzato: posso creare classi, spostarle, creare interfacce, creare collegamenti, ecc.

Quello su cui sto lavorando è la finestra di dialogo per l'impostazione delle proprietà di classe / interfaccia e la creazione di nuove classi / interfacce.

Ad esempio, ho una classe che estende JDialog. Questa è la finestra principale " per la modifica di classi e interfacce (beh, esiste una classe per ciascuna). Contiene un JTabbedPane che a sua volta contiene JPanels.

Questo JPanel è in realtà uno personalizzato. Ho creato una classe astratta che estende JPanel. Questa classe utilizza componenti (definiti dalle sue sottoclassi) e aggiunge i loro valori a una JTable (contenuta anche in JPanel).

Ad esempio, se voglio modificare gli attributi di una classe, JPanel conterrà un JTextField per l'immissione del nome dell'attributo e un altro per l'inserimento del suo tipo. C'è anche una serie di pulsanti per l'elaborazione dei dati inseriti in questi campi. Quando faccio clic su " Salva " ;, i dati che ho inserito in JTextField vengono aggiunti a JTable (à Enterprise Architect). La classe concreta che estende quella astratta è responsabile della definizione del controllo e della decisione su cosa fare con i dati quando una linea viene aggiunta o eliminata dalla tabella JT. La gestione di JTable è, tuttavia, la responsabilità della classe astratta.

Ecco il mio problema: in OO, una classe ha metodi e un'interfaccia ha anche metodi. Mi sono detto: potevo usare lo stesso JPanel personalizzato concreto (AttributesPanel (che estende la classe JPanel astratta che ho creato)) per memorizzare i metodi per una classe o un'interfaccia.

Tuttavia, la classe deve conservare una copia (come attributo) della classe o dell'interfaccia su cui sto lavorando. In questo modo, quando viene aggiunto un metodo, posso chiamare editClass.addMethod () (o editInterface.addMethod ()). Il problema è che non ho modo di dire se lavoro su una classe oe su un'interfaccia.

La soluzione che ho trovato è brutta: mantenere un attributo editClass e un attributo editInterface nella classe AttributesPanel. A seconda che stia modificando una classe o un'interfaccia, uno di questi attributi sarà nullo, mentre l'altro no.

È abbastanza brutto se me lo chiedi. In effetti, posso sentire i miei insegnanti di ingegneria del software nella mia testa urlare di agonia mentre bruciano (beh, in realtà, si congelano) nella nona cerchia dell'Inferno.

Il modo rapido per risolvere questo problema di progettazione sarebbe creare un'interfaccia chiamata " ObjectWithMethods " ;, che verranno implementate dalle mie classi Class e Interface. In questo modo, dovrò solo inserire un parametro ObjectWithMethods nella mia classe AttributesPanel.

Ma ciò significa che dovrei creare una classe denominata " ObjectWithAttributes " ;, o " ObjectWithBlahBlah " ? Vedo qualcosa di buono "TheDailyWTF" potenziale qui ... Inoltre, non penso che dovrei modificare i miei oggetti di dominio (una classe, interfaccia, nota, relazione (per il mio editor UML)) o creare una nuova interfaccia solo per motivi di considerazione dell'interfaccia utente ... .

Cosa ne pensi?

Ho bisogno di ulteriori chiarimenti (perché sono molto stanco in questo momento e tendo a correggere piuttosto male (specialmente in inglese - la mia lingua madre è il francese) mentre in questo stato mentale ...), chiedo e io ' Modificherò questa domanda.

Saluti,

Guillaume.

È stato utile?

Soluzione

Quando leggo la tua domanda sembra davvero che tu stia descrivendo un posto dove usare il modello di visitatore .

Il motivo per cui il modello di visitatore dovrebbe funzionare qui è un'idea nota come doppia spedizione. Il tuo codice UI effettuerà una chiamata e passerà un riferimento a se stesso, quindi la classe o l'interfaccia finisce per chiamare il chiamante originale. Dal momento che la classe o l'interfaccia è quella che chiama il metodo, conosce il proprio tipo e come fare il lavoro specifico per il suo tipo.

Naturalmente, la mia descrizione non è sufficiente per implementare questa tecnica, quindi ti consigliamo di leggerla. Penso che sia ben documentato. Ad esempio, l'ho trovato in circa 2 secondi in Java che dovrebbe iniziare: http://www.javaworld.com/javaworld/javatips/jw-javatip98.html

Altri suggerimenti

Di solito, faccio solo la cosa più semplice e comincio a pensare a fattorizzare le interfacce, quando comincio a vedere troppi costrutti simili a if (.. instanceof ..) nel mio codice. Non mi costa molto con le moderne capacità di refactoring del codice IDE.

Nel tuo caso specifico, prenderei in considerazione l'implementazione dei diagrammi forniti in specifica UML , perché erano così gentili da specificare UML usando la notazione UML!

Hai un'applicazione. In quell'app. rappresenti e modifica alcuni dati.

Questi dati rappresentano una classe del linguaggio di programmazione o un'interfaccia del linguaggio di programmazione.

Quando crei un editor per alcuni dati, a volte devi aggiungere informazioni aggiuntive / complementari, ad esempio ogni grafico di classe può avere un colore di linea diverso e non ha a che fare con gli attributi o i metodi del tuo classe.

Lo stesso vale per il campo o la proprietà che indica chi stai modificando una classe o un'interfaccia.

Suggerisco di fare alcune cose.

Separare i dati rappresentati dal codice o dalla logica del programma:

se hai qualcosa del tipo:

// 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

Modifica in questo:

// 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

Saluti.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top