你们好,今天给你们介绍一个新的设计模式,这个设计模式很是重要,在咱们平常的开发工做当中常用。它就是大名鼎鼎的状态机模式。node
状态机模式很是适合用在复杂的流程或者是系统当中,能够方便咱们对系统的某一个状态进行抽象,这会让咱们编码具备更强的可读性以及延展性。git
首先和你们解释一下状态机当中这个状态的概念,这里的状态指的是咱们系统或者是流程当中的某一个状态。我用我以前作过的一个活动系统来给你们举一个例子。github
好比咱们如今要在网上举办一些活动,而后吸引用户来参与。可是在用户来参与活动的过程中其实有不少的状态须要判断,好比说咱们首先要判断用户是否已经登陆了。若是登陆了,还须要判断用户以前是否报名过,若是已经报名了,还须要判断活动是否开始了等等。web
那么,咱们就能够抽象出不少的状态。好比是否登陆、是否报名、未登陆等等这些都是状态。这些状态之间能够经过一些条件进行转移,好比在初始状态当中,经过判断用户是否登陆选择转移到未登陆状态或者是报名判断的状态上。咱们把这其中的逻辑抽象出来,能够获得这么一张有向无环图。设计模式
几乎全部的固定流程均可以抽象出这么一张图来,这种图通常被缩写成DAG(Directed Acyclic Graph)。若是不用状态机的话,那么咱们须要编写大量的代码来进行判断。就拿上述的这个逻辑举例,咱们须要至少4层if嵌套的逻辑判断来实现这么一个流程。app
若是经过if判断来实现的话,那么面临的一个问题就是这个流程是固定的。若是临时须要改动,那么必需要修改代码,而咱们知道无论大小公司,发布代码都是有严格的规范的,是不能随意发布的。而使用状态机主要解决的就是这个问题,能够把流程作成可配置的,若是须要临时修改,只须要修改状态机的对应配置便可,能够规避掉代码层面的修改。编辑器
理解了DAG以后,咱们再来看看状态机的定义和解释。flex
状态机的官方定义是:编码
The intent of the STATE pattern is to distribute state-specific logic across classes that represent an object’s state. 状态模式会将与状态有关的逻辑分布写在表明对象状态的类中url
这句话英文读起来仍是挺好理解的,中文相对更绕一些。简而言之,machine是一种抽象的概念,表明某一个流程或者是原理,并非咱们理解的机器。因此状态机也不是一个机器,它是由多个表明状态的类组合而成的流程或者说模式。也就是说咱们会把DAG当中的每个节点(状态)单独实现成一个类,那么整个DAG就是一系列状态类构成的图。
对于每一个状态类而言,它们的操做应该都是相似的,就是初始化、执行以及转移。在一些系统当中,甚至能够没有执行只有转移。既然全部状态的操做都是相似的,那么咱们能够对全部的状态抽象出统一的接口。这里咱们多了一个is_end方法,表明某一个状态是不是整个流程的结束,若是是的话,咱们就不须要继续转移了,直接退出便可。
class State:
def __init__(states):
pass
def determine(param):
pass
def operate():
pass
def is_end():
pass
一样,咱们能够实现状态机的类。
class StateMachine:
def __init__():
self.node = StartState()
def init():
self.node = StartState()
def run(param):
while not self.node.is_end():
self.node = self.node.determine(param)
self.node.operate()
因为状态之间转移以及执行的逻辑都被封装在不一样的类当中了,因此对于状态机而言,里面的逻辑很是简单,通常也不须要太大的修改。即便整个流程或者是某一个状态的条件发生变更, 咱们也只须要修改对应节点的代码便可,并不会影响总体,很是适合用在那些流程常常发生变更的场景。
最后,咱们来看一个状态机的使用案例。这个案例源于github,是一个将状态机应用在收音机上的case,具体的细节查看代码便可。
class State:
def scan(self):
# 模拟收音机的仪表盘,只能一个方向转动
self.pos += 1
if self.pos == len(self.stations):
self.pos = 0
print('Scanning... Station is {} {}'.format(self.stations[self.pos], self.name))
class AmState(State):
# Am 音频的类
def __init__(self, radio):
self.radio = radio
self.stations = ['1250', '1380', '1510']
self.pos = 0
self.name = 'AM'
def toggle_amfm(self):
# 转移到Fm
print('Switching to FM')
self.radio.state = self.radio.fmstate
class FmState(State):
# Fm 音频类
def __init__(self, radio):
self.radio = radio
self.stations = ['81.3', '89.1', '103.9']
self.pos = 0
self.name = 'FM'
def toggle_amfm(self):
# 转移到Am
print('Switching to AM')
self.radio.state = self.radio.amstate
class Radio:
# 收音机的总体类,也就是状态机类
def __init__(self):
self.amstate = AmState(self)
self.fmstate = FmState(self)
self.state = self.amstate
def toggle_amfm(self):
self.state.toggle_amfm()
def scan(self):
self.state.scan()
if __name__ == '__main__':
radio = Radio()
actions = [radio.scan] * 2 + [radio.toggle_amfm] + [radio.scan] * 2
actions *= 2
for action in actions:
action()
整个状态机的设计模式自己并不复杂,更多的是对这个设计理念和思想的理解,代码和形式都是表象。
好了,今天的文章就到这里,衷心祝愿你们天天都有所收获。若是还喜欢今天的内容的话,请来一个三连支持吧~(点赞、关注、转发)