OO Design: Algorithm Changing State (Domanda flusso informazioni)

1

Ho un contesto di classe, che contiene un'istanza di uno stato di classe astratto, che ha più sottoclassi concrete (questa è un'implementazione del modello di stato).

Ciascuna sottoclasse di stati esegue un numero di algoritmi, che sono essi stessi classi, e in base al risultato di un algoritmo lo stato nella classe Context potrebbe cambiare.

La mia domanda è: in che modo l'algoritmo dovrebbe apportare questo cambiamento di stato nella classe Context?

1) Una soluzione semplice sarebbe quella di passare l'oggetto Context all'algoritmo, ma non mi piace che l'algoritmo conosca qualcosa sullo stato / contesto corrente.

2) Potrei scrivere classi wrapper specifiche dell'algoritmo della classe Context, in cui ogni wrapper ha una sola funzione pubblica, ovvero impostare lo stato del contesto in base al risultato dell'algoritmo.

3) Passa una funzione di Context che fa cambiare uno stato specifico come puntatore di funzione all'algoritmo ed eseguirlo quando lo stato di Context deve essere modificato.

Mentre 1) è secondo me l'opzione meno favorevole, 2) introdurrebbe un sacco di nuove classi e non sono sicuro di quanto 3) sia fattibile (in C ++) e di quanto sia orientato agli oggetti.

Qual è il modo in cui i libri di testo affrontano questa situazione?

    
posta user695652 18.06.2015 - 16:29
fonte

1 risposta

2

Se la logica per la scelta dello stato successivo fa parte delle classi Algorithm, è chiaro che devono essere in grado di comunicare lo stato specifico per passare alla classe Context.

Se il concetto di stato in cui cambiarsi è inutile senza l'oggetto "contesto" (difficile da dire), passare un riferimento all'oggetto contesto dovrebbe andare bene - gli algoritmi e il contesto dipendono l'uno dall'altro e non c'è nulla che tu possa fallo, quindi rendilo il più esplicito possibile.

Se agli algoritmi non interessa davvero se lo stato cambia o no oa quale stato viene passato (ad esempio, la logica per questo risiede interamente nella sottoclasse dello stato), è possibile passare un functor all'algoritmo da eseguire alla corretta tempo e la sottoclasse di stato implementa quindi il comportamento desiderato (passando a uno stato specifico). Puoi farlo usando una std :: function, o se possibile, passando un lambda come parametro template ad un metodo della classe algoritm (che dovrebbe essere più performante dato che può essere inline - std :: function potrebbe anche fare un'allocazione dell'heap).

Quindi in una sottoclasse di stato potresti avere qualcosa di simile:

void State::ExecuteAlgorithms(Context& context)
{
    algorithm.Execute([&context](){context.switchToState(*something*)});
}

Dove algoritmo.Eseguire sembra:

template<typename CallbackT>
void Algorithm::Execute(CallbackT switchStateCallback)
{
    *code*
    switchStateCallback();
}

Naturalmente potresti voler aggiungere più di un callback o passare parametri al callback, per consentire una logica più complessa per la scelta dello stato successivo.

Puoi sostituire il lambda con una classe (che è comunque implementata internamente) se non li hai disponibili, o usare std :: function invece di un template se l'algoritmo non è solo un singolo metodo o se tu non voglio i modelli.

    
risposta data 18.06.2015 - 19:20
fonte

Leggi altre domande sui tag