The goal is to have well defined state transitions, and the ability to provide the next event to execute.
I'd like to know if this is a proper implementation of State Machine, considering how states and transitionTable are defined, and how I handle event as input and output via update
.
In many examples I cannot clearly define verbiage for state
, so I defined them as verbs (notice ing
suffix), as if it represents the ongoing progress
of workflow. This may be wrong..
I also defined multiple events that could occur for a single state. For example, GetDeviceStatus
and GetIntegrityStatus
events both occur in RetrievingStatus
state. This is also the case for Downloading
state. You can see in the cases, when determining the next event, I need to check what the previous state was first.
If flawed, what are the pitfalls to my design, and how could it be improved? thanks.
enum ExampleState {
case Initiate
case Authorizing // getAuthToken
case RetrievingStatus // getUpdateStatus, getIntegrityCheckStatus
case Downloading // downloadParam, sendParamToPump->RetrieveStatus
case Confirming // confirm
case End
}
enum ExampleEvent {
case InitiateSequence
case GetAuthToken
case GetDeviceStatus
case GetIntegrityStatus
case DownloadFromServer
case DownloadToDevice
case Confirm
}
class StateMachine {
var oldState: ExampleState!
var currentState: ExampleState!
var currentEvent: ExampleEvent!
var table: [ExampleState: [ExampleEvent: ExampleState]] = [.Initiate: [.InitiateSequence: .Authorizing],
.Authorizing: [.GetAuthToken: .RetrievingStatus],
.RetrievingStatus: [.GetDeviceStatus: .Downloading, .GetIntegrityStatus: .Confirming],
.Downloading: [.DownloadFromServer: .Downloading, .DownloadToDevice: .RetrievingStatus],
.Confirming: [.Confirm: .End]]
func update(event: ExampleEvent) -> ExampleEventExecutor? {
let transitionState = table[currentState]![event]!
let oldState = currentState
switch (transitionState) {
case .Initiate:
currentState = .Initiate
return InitiateSequence()
case .Authorizing:
currentState = .Authorizing
return GetAuthToken()
case .RetrievingStatus:
currentState = .RetrievingStatus
switch (oldState) {
case .Authorizing: return GetDeviceStatus()
case .Downloading: return GetIntegrityStatus()
default: return nil
}
case .Downloading:
currentState = .Downloading
switch (oldState) {
case .RetrievingStatus: return DownloadFromServer()
case .Downloading: return DownloadToDevice()
default: return nil
}
case .Confirming:
currentState = .Confirming
return Confirm()
case .End:
currentState = .End
return nil
}
}
}
Aucun commentaire:
Enregistrer un commentaire