Disegni di progettazione per creare oggetti che hanno un elenco di oggetti che hanno anche un elenco di oggetti

5

In termini di buon design OOP, qual è il modo migliore per strutturare il codice che è solo un contenitore di un elenco di oggetti che contiene altri elenchi di oggetti che sono anche solo altri contenitori?

Esempio: un libro di ricette possiede un elenco di capitoli che possiede un elenco di ricette che possiede un elenco di indicazioni stradali. Ogni oggetto è uno strato diverso all'interno di un intero. Per chiarezza, uso la parola "elenco" per fare riferimento a qualsiasi struttura dati utilizzata per memorizzare più oggetti.

Mi sono imbattuto più volte in questo problema con la bambola russa di oggetti annidati all'interno di oggetti nidificati. Ho provato a passare gli oggetti di livello inferiore attraverso la gerarchia dei nidi e ho anche provato a scrivere metodi che trasmettono le informazioni all'oggetto nidificato inferiore. La mia struttura si sente sempre in disordine perché le classi intermedie sono piene di metodi che non fanno altro che passare oggetti o informazioni.

Un'aggiunta dovuta alla confusione espressa nei commenti: Sto cercando una direzione nelle cose da studiare per gestire un tipo generale di problema. Non sto chiedendo una soluzione per un problema di codifica specifico che ho di fronte a me. Non mi aspettavo una "sola risposta per domarli tutti", ma più di "usare un modello di progettazione per le situazioni X ma usare il modello di progettazione B per le situazioni Y e fare attenzione alla Z". L'esempio è per fornire un contesto generale, non specifico.

    
posta WP0987 06.09.2016 - 20:48
fonte

2 risposte

2

Un modo per renderlo più semplice è che tutte le classi implementano la stessa interfaccia in modo da poterle trattare indistintamente. C'è un schema conosciuto per questo :

La buona notizia è che questo crea un albero. Puoi quindi scrivere, in una classe di gestione esterna, metodi ricorsivi per cercare elementi.

Ad esempio potresti scrivere un metodo findAndAdd(String tagToFind, Component componentToAdd);

Per le interfacce di base documentate nel pattern devi aggiungere un tagMatches(String tag) così come tutti i getter e setter comuni in modo da poter, ancora una volta, trattare gli elementi indistintamente della loro classe.

Vorrei aggiungere hasChild() e nextChild() metodi per implementare le iterazioni.

    
risposta data 06.09.2016 - 21:04
fonte
14

Fatti un favore e mantienilo semplice e stupido

Nel tuo esempio, volevi modellare Cookbooks , avendo Chapters , contenente Recipes , proprietaria di Directions . "In termini di buona progettazione OO, modellate esattamente questo: una classe Cookbook con un elenco aggregato di Chapters , con un elenco aggregato di Recipes , ognuno con un elenco di Directions . Si tratta di una semplice mappatura da "oggetti del mondo reale" a "oggetti OOP", che è una delle idee principali di modellazione orientata agli oggetti. È facile da capire e mantenere per te e per chiunque altro debba gestire questi dati.

A questo punto, il tuo codice non è ancora disordinato. Potrebbe diventare complicato se devi spesso scrivere metodi come

 // inside a Cookbook method:
 foreach chapter in listChapters
     foreach recipe in  chapter.listRecipes
          foreach  direction in  recipe.listDirection
              // do something with direction                

Puoi evitare di scrivere questo codice più di una volta se il tuo linguaggio di programmazione ha un buon supporto per la creazione della tua funzione di iteratore (come C # o Python). Quindi è possibile fornire facilmente funzioni di aiuto resuable una sola volta per ottenere, ad esempio, tutte le direzioni in un ricettario. Un altro approccio per utilizzare il modello di visitatore , ti consentirà di fornire diverse operazioni "visitando" tutti gli oggetti in quella gerarchia e fai "qualcosa" durante la visita.

Naturalmente, quando hai contenitori uniform , dove su ogni livello della gerarchia un contenitore può contenere un elenco di contenitori di lo stesso tipo , quindi il modello composito suggerito nella risposta @ TulainsCórdova ha un senso. Esempi per questo sono una gerarchia di file / cartelle o una struttura ad albero per alberi di sintassi astratti, in cui le espressioni contengono sottoespressioni che contengono sottoespressioni e così via. Ma nel tuo esempio, ogni oggetto contenitore che hai descritto su ogni livello è diverso da ogni oggetto su un altro livello, ha un nome diverso, probabilmente un comportamento diverso e contiene solo sotto contenitori di un tipo specifico. Quindi provare a inserire il caso descritto nel pattern composito probabilmente renderà il tuo codice davvero disordinato.

    
risposta data 06.09.2016 - 22:30
fonte

Leggi altre domande sui tag