狀態(tài)模式允許一個(gè)對(duì)象在其內(nèi)部狀態(tài)改變的時(shí)候改變其行為.這個(gè)對(duì)象看上去就像是改變了它的類(lèi)一樣.
環(huán)境(Context)角色,也成上下文:定義客戶端所感興趣的接口枷莉,并且保留一個(gè)具體狀態(tài)類(lèi)的實(shí)例.這個(gè)具體狀態(tài)類(lèi)的實(shí)例給出此環(huán)境對(duì)象的現(xiàn)有狀態(tài).
抽象狀態(tài)(State)角色:定義一個(gè)接口击纬,用以封裝環(huán)境(Context)對(duì)象的一個(gè)特定的狀態(tài)所對(duì)應(yīng)的行為.
具體狀態(tài)(ConcreteState)角色:每一個(gè)具體狀態(tài)類(lèi)都實(shí)現(xiàn)了環(huán)境(Context)的一個(gè)狀態(tài)所對(duì)應(yīng)的行為.
狀態(tài)模式有兩種處理行為一種是所有行為在環(huán)境中進(jìn)行處理璃岳,第二種在狀態(tài)類(lèi)通過(guò)持有環(huán)境(context)進(jìn)行切換.
class Context {
var state:State?
func request(day:Int) {
if day <= 1 {
self.state = BuyState()
} else if day <= 3 {
self.state = SendState()
} else {
self.state = ReceiveState()
}
self.state?.handle()
}
func request2(day:Int) {
self.state = BuyState()
self.state?.innerHandle(day: day, context: self)
}
}
class State {
var context:Context?
func handle() { }
func innerHandle(day:Int,context:Context) { }
}
class BuyState: State {
override func handle() {
print("正在通知快遞公司取件")
}
override func innerHandle(day: Int, context: Context) {
var state:State = self
if day <= 1 {
self.context = context
} else if day <= 3 {
state = SendState()
state.context = context
} else {
state = ReceiveState()
state.context = context
}
state.handle()
}
}
class SendState: State {
override func handle() {
print("商品正在運(yùn)送途中")
}
}
class ReceiveState: State {
override func handle() {
print("已收貨")
}
}
測(cè)試代碼:
let context:Context = Context()
context.request(day: 3)
context.request2(day: 1)
狀態(tài)模式優(yōu)點(diǎn):
1.封裝了轉(zhuǎn)換規(guī)則涡尘,并枚舉可能的狀態(tài)趁冈,它將所有與某個(gè)狀態(tài)有關(guān)的行為放到一個(gè)類(lèi)中歼争,并且可以方便地增加新的狀態(tài)拜马,只需要改變對(duì)象狀態(tài)即可改變對(duì)象的行為.
2.多個(gè)環(huán)境對(duì)象共享一個(gè)狀態(tài)對(duì)象渗勘,從而減少系統(tǒng)中對(duì)象的個(gè)數(shù).
缺點(diǎn):
使用狀態(tài)模式會(huì)增加系統(tǒng)類(lèi)和對(duì)象的個(gè)數(shù),且狀態(tài)模式的結(jié)構(gòu)與實(shí)現(xiàn)都較為復(fù)雜俩莽,如果使用不當(dāng)將導(dǎo)致程序結(jié)構(gòu)和代碼的混亂旺坠,對(duì)于可以切換狀態(tài)的狀態(tài)模式不滿足“開(kāi)閉原則”的要求.