Il modo migliore per visualizzare le informazioni di riepilogo dell'oggetto dominio in modo efficiente e in modo OO da un grande albero di ereditarietà?

1

Ho fornito solo codice semplificato in quanto è più una domanda di disegno astratto.

Quindi ho molti, molti oggetti di eventi business / dominio nidificati, ad es.

 public class Event
 {
  //bunch of properties and standard accessors
 }

 public class ExplosionEvent extends Event
 {
  //properties and standard accessors 
 }

E molti altri di questi a diversi livelli. Se ho bisogno di informazioni su un dato oggetto scelto, lo mostro in HTML così

 private String generateHTML(Event event)
 { 
   StringBuilder sb = new StringBuilder();

   sb.append("<HTML><table>");//simplified

   sb.append("<TH>Time</TH>");   
   sb.append("<TD>" + event.getEventTime() + "</TD>");

   if (event instanceof ExplosionEvent)
   {
     //append HTML and ExplosionEvent specific data
   }

   // ...many, many more calls like the one above

   sb.append("</table></HTML>");
 }

Dato che ho molti tipi di eventi, questo significa un sacco di tag di tabella HTML duplicati e usi di instanceof così generateHTML è lungo centinaia di righe, ovviamente diviso in metodi, ma ancora, è un sacco di codice che rende questo difficile da capire, navigare e quindi mantenere.

Questo è brutto e ho bisogno di un design migliore per questo. Ho avuto l'idea di creare un metodo su Event che è sovrascrivibile da tutti i metodi secondari

//Using LinkedHashMap to preserve order as Properties wont do that
public LinkedHashMap<String, String> getAttributes()
{
 LinkedHashMap<String, String> list = new LinkedHashMap<String, String>();

 list.put("Time", eventTime);
}

le sottoclassi sovrascrivono questo, chiamano i loro genitori e aggiungono la data specifica ad esse nella lista, il che significa che indipendentemente dal numero di classi Event , il metodo esistente generateHTML (esterno a Event oggetti) quindi è sufficiente un piccolo ciclo

private String generateHTML(Event event)
{
  StringBuilder sb = new StringBuilder();

  b.append("<HTML><table>");

  for (Entry<String,String> entry : event.getAttributes().entrySet())
  {
    sb.append("<TH>" + entry.getKey() + "</TH>");   
    sb.append("<TD>" + entry.getValue() + "</TD>");
  }

  sb.append("</table></HTML>");
}

Questo sta mettendo troppa logica negli oggetti business / domain?

C'è un modo migliore ?

    
posta Ross Drew 31.01.2014 - 12:43
fonte

2 risposte

3

Questo mi sembra sospetto ...

if (event instanceof ExplosionEvent)
{
  //append HTML and ExplosionEvent specific data
}

... di solito quando vedo che penso che l'Evento debba essere astratto con un metodo superfluo. Questo metodo è LinkedHashMap<String, String> getAttributes() come suggerito.

Un'altra possibilità è di archiviare LinkedHashMap come membro di Event (pseudo-codice in anticipo):

class Event
{
    LinkedHashMap<String, String> map;
    protected void SetAttribute(String name, String value)
    {
        // stores in map
    }
    protected String getAttribute(String name)
    {
        // gets from map
    }
    LinkedHashMap<String, String> getAttributes()
    {
        // returns entire map
    }
}

class ExplosionEvent inherits Event
{
    String getLocation() { return getAttribute("location"); }
    void setLocation(String location) { setAttribute("location", location); }

}

Potresti prendere in considerazione l'utilizzo della java.utils.Properties per la tua implementazione .

Un'altra soluzione potrebbe essere utilizzare la reflection .

    
risposta data 31.01.2014 - 14:55
fonte
1

Questa è una pessima soluzione perché unisce due aspetti completamente separati - le funzioni primarie dei tuoi oggetti e le sue proprietà come HTML. D'altra parte, immagino tu stia cercando di ottenere l'accesso allo stato privato dell'oggetto, che viola l'astrazione.

Se stai solo provando a stampare questo codice HTML per scopi di debug, la soluzione migliore sarebbe utilizzare il reflection per ispezionare i suoi campi / proprietà. Se hai solo bisogno di stampare alcuni campi, puoi usare le annotazioni per contrassegnare quali campi devono essere controllati con la riflessione.

Se fornire l'accesso ai suoi campi fa parte del progetto, le tue classi dovrebbero fornire il tuo getAttributes come parte di un'interfaccia, ma delegare generateHTML a qualcun altro. In questo modo non è necessario modificare le classi solo perché si desidera modificare la formattazione HTML. Puoi disaccoppiare ulteriormente il codice restituendo Map o Iterator da getAttributes anziché LinkedHashMap .

    
risposta data 10.02.2014 - 20:01
fonte

Leggi altre domande sui tag