1. 程式人生 > >22-Python與設計模式--狀態模式

22-Python與設計模式--狀態模式

一、電梯控制器

電梯在我們周邊隨處可見,電梯的控制邏輯中心是由電梯控制器實現的。電梯的控制邏輯,即使簡單點設計,把狀態分成開門狀態,停止狀態和執行狀態,操作分成開門、關門、執行、停止,那流程也是很複雜的。首先,開門狀態不能開門、執行、停止;停止狀態不能關門,停止;執行狀態不能開門、關門、執行。要用一個一個if…else…實現,首先程式碼混亂,不易維護;二是不易擴充套件。至於各種設計原則什麼的……
那該如何實現?在上邊的邏輯中,每個操作僅僅是一個操作,狀態切換與操作是分離的,這也造成後來操作和狀態“相互配合”的“手忙腳亂”。如果把狀態抽象成一個類,每個狀態為一個子類,每個狀態實現什麼操作,不實現什麼操作,僅僅在這個類中具體實現就可以了。
下面我們實現這個邏輯。
先實現抽象的狀態類:

複製程式碼
class LiftState:
    def open(self):
        pass
    def close(self):
        pass
    def run(self):
        pass
    def stop(self):
        pass
複製程式碼

而後實現各個具體的狀態類:

複製程式碼
class OpenState(LiftState):
    def open(self):
        print "OPEN:The door is opened..."
        return self
    def close(self):
        print "OPEN:The door start to close..."
        print "OPEN:The door is closed"
        return StopState()
    def run(self):
        print "OPEN:Run Forbidden."
        return self
    def stop(self):
        print "OPEN:Stop Forbidden."
        return self
class RunState(LiftState):
    def open(self):
        print "RUN:Open Forbidden."
        return self
    def close(self):
        print "RUN:Close Forbidden."
        return self
    def run(self):
        print "RUN:The lift is running..."
        return self
    def stop(self):
        print "RUN:The lift start to stop..."
        print "RUN:The lift stopped..."
        return StopState()
class StopState(LiftState):
    def open(self):
        print "STOP:The door is opening..."
        print "STOP:The door is opened..."
        return OpenState()
    def close(self):
        print "STOP:Close Forbidden"
        return self
    def run(self):
        print "STOP:The lift start to run..."
        return RunState()
    def stop(self):
        print "STOP:The lift is stopped."
        return self
複製程式碼

為在業務中排程狀態轉移,還需要將上下文進行記錄,需要一個上下文的類。

複製程式碼
class Context:
    lift_state=""
    def getState(self):
        return self.lift_state
    def setState(self,lift_state):
        self.lift_state=lift_state
    def open(self):
        self.setState(self.lift_state.open())
    def close(self):
        self.setState(self.lift_state.close())
    def run(self):
        self.setState(self.lift_state.run())
    def stop(self):
        self.setState(self.lift_state.stop())
複製程式碼

這樣,在進行電梯的排程時,只需要排程Context就可以了。業務邏輯中如下所示:

複製程式碼
if __name__=="__main__":
    ctx = Context()
    ctx.setState(StopState())
    ctx.open()
    ctx.run()
    ctx.close()
    ctx.run()
    ctx.stop()
複製程式碼

列印如下:


STOP:The door is opening...
STOP:The door is opened...
OPEN:Run Forbidden.
OPEN:The door start to close...
OPEN:The dorr is closed
STOP:The lift start to run...
RUN:The lift start to stop...
RUN:The lift stopped...


由邏輯中可知,電梯先在STOP狀態,然後開門,開門時執行Run,被禁止,然後,關門、執行、停止。

二、狀態模式

狀態模式的定義如下:當一個物件內在狀態改變時允許其改變行為,這個物件看起來像改變了其類。


f1.png

 

三、狀態模式的優點和應用場景

優點:

1、狀態模式的優點是結構清晰,相比於if…else…簡約了不少;
2、封裝性好,外部呼叫不必知道內部實現細節。

應用場景:

1、行為狀態改變的場景。這點在各種控制器中非常常見,同時,邏輯結構為狀態轉移圖的場景中都非常適用。

四、狀態模式的缺點

1、在狀態比較多時,子類也會非常多,不便於管理。