Iniezione delle dipendenze con macchine a stati finiti e il principio di segregazione dell'interfaccia

2

Sto cercando di capire qual è il modo migliore per configurare un FSM e anche mantenere pulite le mie interfacce e utilizzare un contenitore IOC per usare DI.

Andiamo a visitare l'esempio di esempio di Head First design pattern of the gumball machine.

interface IState
{
    InsertQuarter();
    EjectQuarter();
    TurnCrank();
    Dispense();
}

La migliore pratica è solo quella di generare un'eccezione per uno stato non valido? Perché aggiungere lo stato se non è nemmeno applicabile? Immagino che sia la parte in cui sono confuso. Potrei vedere questo semplice esempio diventare più complesso.

La mia altra domanda correlata è, come faccio a eseguire DI in questi stati? Dovrebbe essere registrata una macchina di stato e stati nel mio contenitore IOC? Supponiamo che disponga di un servizio ordini e di un servizio di inventario con una dipendenza su StageOrderState . Come potrebbe essere questo modello di oggetto? Sto avendo difficoltà a digerire come effettivamente iniettare le dipendenze in questi stati. La mia ipotesi è che io potrebbe registrare gli stati e passare il contenitore intorno agli stati.

    
posta disjointed 15.10.2013 - 17:49
fonte

2 risposte

2

Mi sembra che tu voglia generalizzare l'esempio Head First, in modo che possa accettare una raccolta arbitraria di azioni.

In C # puoi avere funzioni di prima classe, il che significa che puoi passare funzioni alla tua macchina a stati finiti e mantenerle in una lista. Qualcosa come:

interface IState
{
    void AddStep(Action<T> action);
}

E poi passa la tua funzione al metodo AddStep per l'inserimento nell'elenco dalla macchina a stati.

public class StateMachine : IState
{
    List<Action<T>> actions;

    public void AddStep(Action<T> action)
    {
        actions.Add(action);
    }
}

Quindi aggiungi le tue azioni.

var machine = new StateMachine();
machine.AddStep(x => Console.WriteLine(x.ToString()));
    
risposta data 15.10.2013 - 18:21
fonte
0

Per la prima domanda: gli stati non sono invalidi in generale. Le azioni hanno senso solo in alcuni stati. Ad esempio, chiamare EjectQuarter() non ha senso se non hai precedentemente chiamato InsertQuarter() . Se ciò accade, come vuoi procedere? Nel profondo della logica aziendale, il lancio di un'eccezione ha senso (non esiste un modo ragionevole di procedere); cattura tale eccezione e visualizza un messaggio di errore nel livello dell'interfaccia utente.

Per la tua seconda domanda, non penso che DI sia inteso per stati (valori); è pensato per iniettare servizi da cui dipendono altri servizi. È possibile iniettare un intero FSM in un servizio di inventario; se si dispone di metodi che dovrebbero comportarsi in modo diverso a seconda dello stato in cui si trova un FSM, passare lo stato a tali metodi o passare l'FSM al servizio di inventario e lasciare che chieda al FSM il suo stato corrente. (Raccomando la prima opzione: non vedo alcun motivo per cui un servizio di inventario sappia cos'è un FSM.)

    
risposta data 22.10.2013 - 16:30
fonte