No, non esiste assolutamente un modello standard.
Il mio consiglio è di evitare il trabocchetto del progettista OO per i principianti cercando di trovare un'unica interfaccia di "classe base" comune per tutto. Il tuo drago è molto diverso dal tuo mago e non c'è nulla da guadagnare tentando di unire le due interfacce, tranne le astrazioni di codice. Ricorda, l'ereditarietà non è uno strumento per il riutilizzo del codice.
L'approccio più semplice è che ogni oggetto mantenga il proprio stato interno (come già descritto) e sia in grado di disegnare quello stato. Questo è il punto in cui un'istruzione switch vecchia scuola può essere più chiara dell'utilizzo del polimorfismo per lo stesso effetto. Esempio:
class Dragon {
enum State { asleep, flying, breathing_fire };
public:
void draw() { /* old-school switch */
switch (cur_state){
case asleep: draw_asleep();
case flying: draw_flying();
case breathing_fire: draw_breathing_fire();
}
}
private:
void draw_asleep();
void draw_flying();
void draw_breathing_fire();
};
esperti sviluppatori C++ si gasp al codice di cui sopra (come dovrebbero), perché l'istruzione switch è quasi esattamente quello che una chiamata di metodo polimorfico avrebbe compiuto - runtime spedizione. (O ancora più criptico: una tabella di indirizzi di metodo). La mia opinione personale è che per questo specifico tipo di classe, cioè una singola interfaccia pubblica che incapsula una macchina a stati, l'istruzione switch è più chiara e mantenibile perché rende la macchina a stati salta esplicitamente. Penso sia anche chiaro che riconosco che questo è generalmente design C++ non valido.
L'attrito di questo design è causato dalla linea divisoria tra la macchina a stati e la singola interfaccia pubblica. Un drago dormiente non è chiaramente lo stesso di un drago volante. In effetti, non avrà praticamente nulla in comune. Ma il design di livello più alto dice che i due sono il drago SAME. Che casino! Crei oggetti Dragon diversi per ogni stato? No, perché questo esporrebbe il concetto di stato al chiamante. Crei diversi oggetti helper interni per ogni stato e li spedisci a quelli? Forse, ma diventa molto veloce. L'approccio di cui sopra è un compromesso tra i due.Pensa all'affermazione dell'intervento come se isolasse la bruttezza. L'interfaccia pubblica è pulita, così come l'interfaccia privata. Solo l'istruzione switch contiene il pasticcio sporco. Considera questo approccio e considera anche altri suggerimenti.
Infine, per attirare la vostra Wizard e il vostro drago, un semplice modello di involucro o funtore sarà sufficiente:
struct Draw {
template <class S>
void operator()(S& s) { s.draw(); }
};
Il punto è che non c'è bisogno di unire due classi diverse solo perché entrambi supportano il stessa operazione logica.
Ruba idee da giochi open source esistenti. –
std :: map - per archiviazione interna da stato a animazione e qualsiasi formato aperto per archiviazione esterna. –
W55tKQbuRu28Q4xv