Possiedo un set di classi, ognuna delle quali deve decidere a un certo punto quale di due o tre approcci utilizzare internamente per implementare esternamente la stessa funzionalità. Idealmente, questo dovrebbe includere la funzionalità di fallback, dove se ApproachA fallisce, cade per provare ApproachB (e forse si avvicina a C, D, ecc.). Fino ad ora, ho appena usato la codifica come if (!success) { ApproachB code }
. Il problema con questo è che diversi metodi successivi devono anche essere a conoscenza di quale approccio è stato scelto e tutti sviluppano anche le proprie dichiarazioni if (MethodChosen) { } else { }
. Voglio davvero affrontare il problema con qualcosa di meno ingombrante ... tranne che nessuna delle altre opzioni che ho considerato sembra tutta "maneggevole". Ecco i tre approcci che ho pensato:Implementazione di classi "fallback"
- Implementare un metodo .Create statico che decide quale delle due classi derivate creare, in cui le due classi dispongono di un'interfaccia che le supporta. Lo svantaggio di questo è che stai scrivendo due volte lo stesso codice, e in realtà non sta creando una "ripiego" poiché impone che tutto il processo decisionale venga eseguito in anticipo nel metodo .Create. Questo dovrebbe funzionare 9/10 volte, ma ci saranno le altre 1/10 volte in cui voglio che il fallback entri in gioco solo quando il primario ha tentato e fallito.
- Lo stesso come sopra, ma con una classe base o astratta coinvolta, sia come classe di supporto per entrambi, sia con il primario come classe base per il fallback. Questo ha lo stesso svantaggio di fallback, ma almeno c'è poco o nessun codice ripetuto.
implementare una classe astratta normalmente costruita con classi figlie che può essere modificato in fase di esecuzione: cioè
public void SomeMethodOrConstructor() { if (someConditions) MyChild = ChildClassA; else MyChild = ChildClassB; } public void Execute() { MyChild.Execute(); }
Il problema con l'opzione 3 sta passando dati tra i due quando necessario. Poiché alcuni di questi metodi stanno modellando oggetti esterni, ciò sarà abbastanza frequente. Le classi nidificate condividono automaticamente i dati con la loro classe genitore? O dovrò passare tutto con ogni chiamata?
Qualcos'altro che dovrei considerare?
Aggiornamento: la prima classe è attiva e funzionante con la catena di responsabilità. Per ora, ho deciso di non utilizzare il modello di strategia o il fallback durante l'esecuzione del metodo, poiché credo che alla fine non sia necessario. Penso che la maggior parte di tali fallimenti di esecuzione saranno in effetti migliori se si manterranno all'interno delle proprie classi, dal momento che non ci sarà un cambio completo di gameplan, solo alcune piccole modifiche da affrontare. Se questo risulta non essere il caso, almeno so di cosa ho bisogno per indagare ora.
Grazie a tutti coloro che hanno contribuito con la soluzione definitiva!
Per i curiosi, la mia soluzione definitiva lavorato più o meno in questo modo:
- Creare Handler classe astratta, più o meno come indicato nella voce di Wikipedia, ma con una funzione
public abstract Handler GetHandler()
, e l'aggiunta di altri metodi astratti come carico, Salva, ecc. - Implementare sottoclassi di handler privati per la classe genitore (potrebbero anche essere sottoclassi, dato che gestiranno solo le cose per quella particolare classe ... eviteranno anche problemi di denominazione successivi). Le classi figlie prendono tutti un parametro del tipo dell'oggetto genitore nel loro costruttore, in modo da avere un facile accesso ai dati del genitore.
- Dal costruttore della classe genitore, impostare Chain of Responsibility handler/successors (sempre, proprio come nell'esempio), quindi chiamare
FirstHandler.GetHandler(this)
e memorizzare il risultato in modo che la classe sappia quale gestore utilizzare in futuro. - La maggior parte dei metodi gestiti viene quindi ridotta a
Handler.MethodName()
.
È possibile inserire il codice in un elenco numerato indentandolo con _eight_ spazi. – SLaks
Grazie per il suggerimento di formattazione, che mi stava guidando sul muro! – RobinHood70