State Mode: 状态模式
对象收到信息,对应状态发生变化,这是软件中常见的一种运作方式。对象我们将状态作为一个独立的对象,主对象的不同状态切换只需要切换状态对象即可。
The state mode enable the class to change its behavior when its inner state changed. The StateContext
only do the switch work, and the detail work is done by State
object. The context manage the statements in a high level, it can switch some different state when we need. The context inject a reference to the concrete state object to enable the state to delegate the detail work.
状态模式中,当对象的状态改变时,对象的行为随着改变。状态上下文类只执行状态切换工作,具体的工作细节交给状态对象去执行。上下文对象在一个较高的层次管理着自身的状态,它可以在我们有需要的时候切换不同的状态。上下文对象注入了一个自己的引用给状态对象,使得状态对象可以代理在切换状态时候的细节工作。
// Abstract state
class State {
var context: Context?
var name: String = ""
init(context: Context?) {
self.context = context
}
}
// Concrete state
class NewState: State {
override init(context: Context?) {
super.init(context: context)
self.name = "New"
}
func start() {
print("Call start")
if self.name == "New" {
context?.setState(state: RunnableState(context: context))
} else {
print("Can't go to runnable")
}
}
}
// Concrete state
class RunnableState: State {
override init(context: Context?) {
super.init(context: context)
self.name = "Runnable"
}
func getCpu() {
if self.name == "Runnable" {
context?.setState(state: RunningState(context: context))
} else {
print("Can't go to running")
}
}
}
// Concrete state
class RunningState: State {
override init(context: Context?) {
super.init(context: context)
self.name = "Running"
}
func suspend() {
if self.name == "Running" {
context?.setState(state: BlockState(context: context))
}
}
func stop() {
if self.name == "Running" {
context?.setState(state: DeadState(context: context))
}
}
}
// Concrete state
class BlockState: State {
override init(context: Context?) {
super.init(context: context)
self.name = "Block"
}
func resume() {
if name == "Block" {
context?.setState(state: RunnableState(context: context))
}
}
}
// Concrete state
class DeadState: State {
override init(context: Context?) {
super.init(context: context)
self.name = "Dead"
}
}
// Thread Context
class Context {
private var state: State?
init() {
self.state = NewState(context: self)
}
func setState(state: State) {
self.state = state
}
func getState() -> State? {
return self.state
}
func start() {
if let s = self.state as? NewState {
s.start()
}
}
func suspend() {
if let s = self.state as? RunningState {
s.suspend()
}
}
func resume() {
if let s = self.state as? BlockState {
s.resume()
}
}
func getCpu() {
if let s = self.state as? RunnableState {
s.getCpu() // It will switch to the running state.
}
}
func stop() {
if let s = self.state as? RunningState {
s.stop()
}
}
}
let context = Context()
context.start() // It will be runnable then.
context.getCpu() // It will be running then.
context.suspend() // It will be blocked then.
context.resume() // It will be runnable then.
context.getCpu() // It will be running then.
context.stop() // It will be dead then.
以上代码中,不同状态类都遵守 State 协议,context 对象具备一个 state,调用 context 的方法可以使得 context 在不同状态之间切换。State 协议持有 Context 类型引用,具体状态对象可以调用 context 对象进行具体的操作。