Come implementare stati che non si escludono a vicenda

3

Sto lavorando su un'applicazione GUI usando il pattern MVC, ma il controller ha dimostrato di essere molto più complicato di quanto pensassi all'inizio.

L'applicazione ha opzioni che determinano il funzionamento delle operazioni nei listener di azione, quindi ho iniziato a utilizzare il modello di progettazione dello stato. Ma poi ho capito che le opzioni (stati) non si escludono a vicenda. Puoi avere due stati diversi allo stesso tempo.

Tutte le implementazioni del pattern State presuppongono che gli stati si escludono a vicenda. Come posso implementarlo in modo tale che sia possibile attivare più stati contemporaneamente e mi consente di aggiungere nuovi stati in un secondo momento senza modificare il codice?

    
posta William 28.12.2016 - 18:54
fonte

3 risposte

4

Sembra che tu abbia più tipi di stato ma non li hai ancora riconosciuti tutti. Quindi hai iniziato a catturarli in un unico set. Ad esempio, puoi avere questo enum per lo stato di un lavoro:

{In coda, in esecuzione, PausaPending, In pausa, Ripresa, Annulla in sospeso, Annullato, Interrotto, Completato}

E questo può sembrare OK e completo. Fino a quando non noti che il lavoro è ancora in esecuzione dopo che l'utente ha emesso una richiesta di annullamento fino a quando non viene effettivamente annullata. Quindi qual'è il suo stato nel frattempo?

Sembra che l'aumento di una richiesta di annullamento sia indipendente dallo stato del lavoro, quindi non è uno stato di lavoro. È una richiesta di modifica dello stato del lavoro.

Quindi hai davvero due tipi:

JobState {In coda, In esecuzione, In pausa, Annullato, Interrotto, Completato}

JobStateChangeRequest {None, Pause, Resume, Cancel}

Sospetto che tu abbia un problema simile tra le mani.

    
risposta data 28.12.2016 - 21:44
fonte
2

Il schema di progettazione dello stato utilizza la composizione per mantenere un oggetto stato corrente e delegarlo a richieste specifiche dello stato. L'oggetto stato ha una classe derivata da una classe di stato astratta. Questo disegno presuppone infatti che gli stati si escludano a vicenda.

Se gli stati della tua applicazione non si escludono a vicenda, puoi avere diverse macchine di stato o hanno stati compositi.

1.Multiple state machines

Se le macchine a stati sono completamente indipendenti e ciascuna macchina a stati è responsabile di un insieme di richieste mutuamente esclusive, applicare più volte il modello di progettazione stato, con oggetti di stato indipendenti. La separazione delle preoccupazioni (due macchine a stati) lo rende molto facile da mantenere. Esempio:

class StateA {     // first family of states
public:  
    void doUpdate()=0;    // handling one kind of requests 
}; 
class StateA1 : public StateA { 
    ...
}; 

class StateB {     // second family of states 
public:  
    void doDelete()=0;   // handling another kind of requests
}; 
class StateB1 : public StateB { 
    ...
}; 

class Context {
private: 
    StateA *a;    // independent states 
    StateB *b;  
...
};

Se le macchine a stati sono indipendenti, ma sfortunatamente la gestione delle richieste dipende dalla combinazione degli stati, questa tecnica non funzionerà in generale. Quindi potresti:

  • usa lo schema di progettazione dello stato, ma crea stati concreti combinati (con o senza sottoclasse, o eventualmente usando ereditarietà multipla). Ciò sarà doloroso non solo per l'implementazione di nuove combinazioni ogni volta che si aggiunge un nuovo stato, ma anche per la gestione di tutte le nuove transizioni di stato.
  • combina il modello di stato, con il motivo decoratore o schema di strategia . Questo potrebbe evitare un codice ridondante, ma lascerà comunque le transizioni di stato orribili da mantenere.

2. Macchine a stati annidati

Con gli stati compositi, alcuni stati principali si escludono a vicenda. Tuttavia, alcuni di essi hanno uno stato secondario (che può dipendere dallo stato principale). In questo caso, hai bisogno di macchine a stati nidificati:

  • l'approccio della forza bruta sarebbe quello di lavorare con un modello di stato classico, ma di sottoclasse ulteriormente gli stati principali che lo richiedono. Di nuovo, sarà doloroso mantenere le transizioni di stato ogni volta che aggiungerai un nuovo stato secondario.
  • potrebbe essere fattibile implementare lo stato principale usando uno schema di stato e implementare un sotto-stato negli stati principali concreti che lo richiedono. Questo approccio è di nuovo meno accoppiato e più facile da mantenere.
risposta data 28.12.2016 - 20:25
fonte
1

Ciò che potrebbe esserti utile è Schema della catena di responsabilità . Si modella ogni stato come un collegamento nella catena e quindi si inviano gli eventi a modo loro. In questo modo, più di un link può reagire a un evento.

Purtroppo, senza ulteriori dettagli su ciò che stai cercando di fare, non posso fornire ulteriori dettagli.

    
risposta data 28.12.2016 - 19:27
fonte

Leggi altre domande sui tag