狀态模式:對象行為是根據狀态改變,而改變的。
專注前端與算法的系列幹貨分享。
引用請聲明:xxoo521.com | 「公衆号:心譚部落格」
什麼是“狀态模式”?
狀态模式:對象行為是根據狀态改變,而改變的。
正是由于内部狀态的變化,導緻對外的行為發生了變化。例如:相同的方法在不同時刻被調用,行為可能會有差異。
優缺點
優點:
- 封裝了轉化規則,對于大量分支語句,可以考慮使用狀态類進一步封裝。
- 每個狀态都是确定的,對象行為是可控的。
缺點:狀态模式的實作關鍵是将事物的狀态都封裝成單獨的類,這個類的各種方法就是“此種狀态對應的表現行為”。是以,程式開銷會增大。
代碼實作
ES6 實作
在 JavaScript 中,可以直接用 JSON 對象來代替狀态類。
下面代碼展示的就是 FSM(有限狀态機)裡面有 3 種狀态:
download
、
pause
、
deleted
。控制狀态轉化的代碼也在其中。
DownLoad
類就是,常說的
Context
對象,它的行為會随着狀态的改變而改變。
const FSM = (() => {
let currenState = "download";
return {
download: {
click: () => {
console.log("暫停下載下傳");
currenState = "pause";
},
del: () => {
console.log("先暫停, 再删除");
}
},
pause: {
click: () => {
console.log("繼續下載下傳");
currenState = "download";
},
del: () => {
console.log("删除任務");
currenState = "deleted";
}
},
deleted: {
click: () => {
console.log("任務已删除, 請重新開始");
},
del: () => {
console.log("任務已删除");
}
},
getState: () => currenState
};
})();
class Download {
constructor(fsm) {
this.fsm = fsm;
}
handleClick() {
const { fsm } = this;
fsm[fsm.getState()].click();
}
hanldeDel() {
const { fsm } = this;
fsm[fsm.getState()].del();
}
}
// 開始下載下傳
let download = new Download(FSM);
download.handleClick(); // 暫停下載下傳
download.handleClick(); // 繼續下載下傳
download.hanldeDel(); // 下載下傳中,無法執行删除操作
download.handleClick(); // 暫停下載下傳
download.hanldeDel(); // 删除任務
複制
Python3 實作
python 的代碼采用的是“面向對象”的程式設計,沒有過度使用函數式的閉包寫法(python 寫起來也不難)。
是以,負責狀态轉化的類,專門拿出來單獨封裝。
其他 3 個狀态類的狀态,均由這個狀态類來管理。
# 負責狀态轉化
class StateTransform:
def __init__(self):
self.__state = 'download'
self.__states = ['download', 'pause', 'deleted']
def change(self, to_state):
if (not to_state) or (to_state not in self.__states) :
raise Exception('state is unvalid')
self.__state = to_state
def get_state(self):
return self.__state
# 以下是三個狀态類
class DownloadState:
def __init__(self, transfomer):
self.__state = 'download'
self.__transfomer = transfomer
def click(self):
print('暫停下載下傳')
self.__transfomer.change('pause')
def delete(self):
print('先暫停, 再删除')
class PauseState:
def __init__(self, transfomer):
self.__state = 'pause'
self.__transfomer = transfomer
def click(self):
print('繼續下載下傳')
self.__transfomer.change('download')
def delete(self):
print('删除任務')
self.__transfomer.change('deleted')
class DeletedState:
def __init__(self, transfomer):
self.__state = 'deleted'
self.__transfomer = transfomer
def click(self):
print('任務已删除, 請重新開始')
def delete(self):
print('任務已删除')
# 業務代碼
class Download:
def __init__(self):
self.state_transformer = StateTransform()
self.state_map = {
'download': DownloadState(self.state_transformer),
'pause': PauseState(self.state_transformer),
'deleted': DeletedState(self.state_transformer)
}
def handle_click(self):
state = self.state_transformer.get_state()
self.state_map[state].click()
def handle_del(self):
state = self.state_transformer.get_state()
self.state_map[state].delete()
if __name__ == '__main__':
download = Download()
download.handle_click(); # 暫停下載下傳
download.handle_click(); # 繼續下載下傳
download.handle_del(); # 下載下傳中,無法執行删除操作
download.handle_click(); # 暫停下載下傳
download.handle_del(); # 删除任務
複制
參考
- 23 種設計模式全解析
- 菜鳥教程狀态模式
- 《JavaScript 設計模式與開發實踐》