2012-01-02 11 views
7

Ho un gruppo di classi che estendono una singola classe astratta. Un sottoinsieme di queste classi richiede una implelmentazione identica di uno dei metodi, un altro sottoinsieme delle classi richiede un'altra implementazione del metodo e un terzo sottoinsieme ne richiede un altro. In tutto ci sono una decina di classi figlio, ma solo tre possibili implementazioni di uno dei metodi. (Esistono molti altri metodi implementati dalle classi che non hanno nulla in comune.)Come fare questo senza ereditarietà multipla

Sto cercando di capire il modo migliore per farlo. Penso che quello che avrei fatto in C++ è l'ereditarietà multipla: crea tre classi che implementano solo questo metodo, quindi i figli ereditano da quella appropriata di quelle tre classi.

Esiste una best practice per fare questo in Java?

Stavo considerando uno strato intermedio di tre classi astratte, tra la classe astratta principale ei bambini. Ognuno dei tre che eredita dalla principale classe astratta e implementa il metodo in questione. Quindi i bambini ereditano da questi tre. Ma quello che non mi piace è che cosa succede se un altro metodo ha un simile comportamento di "raggruppamento", e non corrisponde alle tre classi "middle tier"? Sarebbe brutto

Qualcosa di tutto questo ha senso? Sto scrivendo di fretta ...

MODIFICA: Così, 24 ore dopo aver fatto la mia domanda, ho ricevuto circa una mezza dozzina di modelli da investigare. Non sono ancora sicuro che siano tutti nomi ufficiali di design pattern. Ma esaminerò ciascuno e poi riferirò (e sceglierò una risposta corretta). Gli zoccoli proposti finora:

* Delegation 

* Bridge 

* Strategy 

* Composition 

* Decorator (if I was choosing on name alone, I choose this one) 

ho anche bisogno di aggiungere che il metodo che è in corso di attuazione ha bisogno di accedere a quasi tutti i membri privati ​​della classe. Quindi questo sarà un fattore importante nella mia scelta.

risposta

3

Se si insiste a risolverlo tramite l'ereditarietà, lo bridge pattern del libro GoF potrebbe aiutare qui (potrebbe essere o non essere un adattamento perfetto, a seconda dei domini del dominio che causano la separazione in tre implementazioni). Personalmente, probabilmente inserirò le tre implementazioni del metodo in una classe helper e inoltrerò le chiamate al metodo dalle classi (ciò a cui JB Nizet si riferisce correttamente come delegazione).

+0

Grazie per il link, leggerò e tornerò con le mie domande. Continuerai ad ascoltare? Sono nuovo qui. I commenti postati per le risposte causano un tipo di avviso da inviare al rispondente? –

+0

I commenti alle risposte fanno scattare una piccola notifica, ma se avete domande successive è più nello spirito del sito Web pubblicarli come nuovi (controllando la presenza di duplicati) invece di richiedere risposte di follow-up su quella precedente. La meta-discussione come questa ha [il proprio sito secondario] (http://meta.stackoverflow.com/) ed è qui disapprovata. – Barend

6

Utilizzare la delega piuttosto che l'ereditarietà. Tutte le classi di uno stesso gruppo delegano a un oggetto helper comune per implementare il loro metodo.

+0

Penso che anche i modelli di Bridge e Strategy si riducano alla delegazione. Quale dei modelli sarebbe la migliore secondo te? O dovremmo fare a meno dei modelli qui (per quanto una classe helper non è un modello tutto da solo)? Penso che il richiedente sia rimasto con più risposte, tutte non sbagliate da sole ... –

+0

Il modello di strategia è quello che sembra il più appropriato, tranne che il modello strategico consiste nell'iniettare una strategia in una classe. In questo caso, non penso che le classi debbano essere configurabili dall'esterno. Un metodo deve essere semplicemente esternalizzato dalla classe. Tutto non deve avere un nome di modello e una semplice delega potrebbe essere sufficiente qui. –

+0

concordato. I pattern sono belli, ma non dovrebbero essere usati in luoghi in cui non sono * pienamente * appropriati. –

1

La soluzione di fuoco rapido semplice senza utilizzare l'ereditarietà sarebbe quella di astrarre i 3 "metodi comuni" altrove, quindi ripetere semplicemente la chiamata al metodo.

Se vuoi farlo in un modo OO bello, dai un'occhiata al modello di decoratore che potrebbe aiutarti in questo modo: crea le tue 3 classi standard che implementano i tre metodi scelti e poi "decorali" con l'altro classi.

1

Innanzitutto, è consigliabile sostituire la classe astratta con un'interfaccia. Non so se è possibile nel tuo caso.

In secondo luogo, è possibile delegare la funzionalità del proprio metodo di "raggruppamento" a un'altra classe (implementatore). Crea 3 diverse classi con l'implementazione del metodo (o solo 3 diversi metodi in alcune classi) e chiamale da classi figlio secondo necessità.

Quindi, il metodo di "raggruppamento" sarà definito in ogni classe figlia ma chiamerà solo uno dei 3 possibili implementatori.

7

In realtà, sento un motivo strategico qui.

Si potrebbe avere quel metodo nel delegato della classe base in una strategia che viene passata in costruzione. Le sottoclassi passano in uno qualsiasi di una serie di strategie come parte della loro costruzione. Le Strategie stesse potrebbero essere rese disponibili sia al di fuori della classe, sia internamente come classi private. Questo potrebbe finire con meno classi in generale nella tua gerarchia.

Detto questo, qui ci sono altri odori, anche con la mia soluzione proposta. Potresti voler pensare ad un livello superiore con le interfacce (come menzionato da altre soluzioni) e la composizione solo senza ereditarietà. Col passare del tempo sono giunto alla conclusione che l'eredità NON è mio amico. Al giorno d'oggi lo evito dove possibile.

+0

Una strategia non deve essere applicata solo a 1 metodo. Posso avere una strategia che implementi più metodi (se sono raggruppati in quel modo). Posso anche avere più interfacce e implementazioni di strategia per ciascuno, quindi combinarle, se necessario, durante la costruzione. Solo un pensiero. Non deve essere la migliore risposta. EDIT: Questa è stata una risposta a un commento che è stato rimosso * mentre * Ho digitato. :) – rfeak

+0

Mi piace così tanto la risposta che ho rimosso la mia. Il modello di strategia può anche essere usato una seconda volta se anche uno dei metodi deve essere condiviso tra le classi. – toto2

+0

Siamo spiacenti, ho rimosso il commento ... era sbagliato e così è stata la mia risposta. Ma come puoi vedere dal mio più recente commento sopra, sono completamente d'accordo con te. – toto2

Problemi correlati