Progettazione del software: raccomandare un approccio per evitare di tagliare / cancellare il tipo qui

6

Ecco un esempio concreto minimo per formulare la mia domanda:

Nel gioco a palla piccola, hai un motore fisico che sposta gli oggetti regolarmente:

void move(set< PhysicalObject* > objets, Duration t)

E quel motore può usare il comportamento definito dall'utente quando avviene una collisione (usando una classe di strategia). Ad esempio, la strategia predefinita è di aggiornare le direzioni degli oggetti, ma puoi fornirle una classe di strategia personalizzata che uccide gli oggetti in base ad alcune regole specifiche.

void update_after_collision(DerivedObject* a, DerivedObject* b)

Per implementare un nuovo comportamento durante una collisione, ho alcune classi derivate specifiche (hanno attributi / metodi aggiuntivi corrispondenti alla loro durata, ecc.)

Il problema è: il motore chiama la strategia update_after_collision, quindi non posso usare la mia classe derivata è questa strategia senza usare un pattern visitor o un cast di tipo. Nota che il motore conosce solo la classe base, non quelli derivati.

C'è un modo per evitarlo? Qual è l'approccio standard da osservare?

Un altro paradigma di programmazione è migliore per questo caso particolare?

EDIT: il codice è scritto in C ++

    
posta Julien__ 18.01.2016 - 22:51
fonte

1 risposta

3

Quello che hai qui è un tipico caso d'uso di runtime multipunto di runtime e, a seconda dell'effettivo linguaggio orientato agli oggetti che intendi usare, questo è integrato o richiede un po 'di lavoro. Mi spiace che questa risposta non possa essere più precisa, ma dipende in gran parte dall'effettivo linguaggio di programmazione.

Assumendo un linguaggio Java-esque, è possibile ideare rapidamente un metodo di invio personalizzato: una semplice organizzazione di "classi" in un tipo enumerato può essere sufficiente all'inizio e abbastanza semplice da modificare. Ogni oggetto contiene un tag type che indica a quali tipi appartiene.

Il tuo metodo di collisione può contenere una matrice quadrata di callback specializzati per ogni combinazione di tipi. In pseudo-codice:

collisions[from.tag][to.tag]

... si riferisce al metodo che devi chiamare con gli oggetti from e to . È possibile estendere il set di tag, ma ciò richiede una fase di ricompilazione. Ma i tag di associazione a metodi efficaci possono essere eseguiti in fase di esecuzione durante il debug, se lo si desidera.

Se vuoi introdurre l'ereditarietà, questo diventa un po 'più complicato: immagina non ci sia un metodo specifico per un tag T (una cella vuota nella matrice collisions ), dovresti tornare al suo tipo genitore P(T) (assumendo l'ereditarietà singola). Per questo potresti avere un membro parent all'interno di ogni tuo valore enum.

Per C ++, dai un'occhiata a Apri Multi-Metodi per C ++ da Stroustrup et al.

    
risposta data 18.01.2016 - 23:40
fonte

Leggi altre domande sui tag