Skip to content

Instantly share code, notes, and snippets.

@scottymac
Last active April 8, 2021 19:03
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
Star You must be signed in to star a gist
Save scottymac/3b3b5335b497dbc30a26 to your computer and use it in GitHub Desktop.
State pattern
// The MIT License
//
// Copyright (c) 2015-2017 Scott McMillin
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
class Mediator<P: MediatorDelegateProtocol> {
fileprivate unowned let delegate: P
var transitions: [Transition<P.StateType>] = []
fileprivate var _state: P.StateType
var state: P.StateType {
get {
return _state
}
set {
transitionTo(newValue)
}
}
init(initialState: P.StateType, delegate: P) {
self.delegate = delegate
_state = initialState
}
func addTransitionFromState(_ fromState: P.StateType, toState: P.StateType, perform: @escaping () -> ()) {
if !hasTransition(fromState, toState: toState) {
transitions.append(Transition(fromState: fromState, toState: toState, perform: perform))
}
}
fileprivate func transitionTo(_ toState: P.StateType) {
guard let t = getTransition(state, to: toState) else {
return
}
_state = toState
t.perform()
}
func getTransition(_ from: P.StateType, to: P.StateType) -> Transition<P.StateType>? {
for t in transitions {
if (t.fromState == from) && (t.toState == to) { return t }
}
return nil
}
func hasTransition(_ fromState: P.StateType, toState: P.StateType) -> Bool {
getTransition(fromState, to: toState) != nil
}
}
struct Transition<T> {
var fromState: T
var toState: T
var perform: () -> ()
}
protocol MediatorDelegateProtocol: class {
associatedtype StateType:Equatable
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment