protocol State { var manager: AppUpdateManager { get } init(manager: AppUpdateManager) } protocol UpdateProcessControlling { func startUpdate() func postponeUpdate() } public class AppUpdateManager { var currentState: State init() { currentState = UpToDate(manager: self) } internal func transition(to: S.Type) { currentState = S(manager: self) } public func startUpdate() { (currentState as? UpdateProcessControlling)?.startUpdate() } } // MARK: - UpToDate struct UpToDate: State, UpdateProcessControlling { let manager: AppUpdateManager init(manager: AppUpdateManager) { self.manager = manager } func startUpdate() { // execute update logic etc. manager.transition(to: Updating.self) } func postponeUpdate() { // execute postponed logic etc. manager.transition(to: Postponed.self) } } // MARK: - Updating struct Updating: State { let manager: AppUpdateManager init(manager: AppUpdateManager) { self.manager = manager } } // MARK: - Postponed struct Postponed: State { let manager: AppUpdateManager init(manager: AppUpdateManager) { self.manager = manager } }