實現有狀態物件或狀態機

2021-10-04 00:21:52 字數 4260 閱讀 2885

想實現乙個狀態機或可以在許多不同狀態下執行的物件,但又不想在**中新增很多條件。

一般通過新增不同狀態符號來執行不同狀態下的**,如下:

class connection:

def __init__(self):

self.state = 'closed'

def read(self):

if self.state != 'open':

raise runtimeerror('not open')

print('reading')

def write(self, data):

if self.state != 'open':

raise runtimeerror('not open')

print('writing')

def open(self):

if self.state == 'open':

raise runtimeerror('already open')

self.state = 'open'

def close(self):

if self.state == 'closed':

raise runtimeerror('already closed')

self.state = 'closed'

該實現存在兩個困難。 首先,由於引入了許多狀態條件檢查,因此**變得很複雜。 其次,由於通用操作(例如read()和write())總是在進行操作之前檢查狀態,因此效能會降低。

一種更優雅的方法是將每個操作狀態編碼為乙個單獨的類,並安排connection類委派給該狀態類。如下:

class connection:

def __init__(self):

self.new_state(closedconnectionstate)

def new_state(self, newstate):

self._state = newstate

# delegate to the state class

def read(self):

return self._state.read(self)

def write(self, data):

return self._state.write(self, data)

def open(self):

return self._state.open(self)

def close(self):

return self._state.close(self)

# connection state base class

class connectionstate:

@staticmethod

def read(conn):

raise notimplementederror()

@staticmethod

def write(conn, data):

raise notimplementederror()

@staticmethod

def open(conn):

raise notimplementederror()

@staticmethod

def close(conn):

raise notimplementederror()

# implementation of different states

class closedconnectionstate(connectionstate):

@staticmethod

def read(conn):

raise runtimeerror('not open')

@staticmethod

def write(conn, data):

raise runtimeerror('not open')

@staticmethod

def open(conn):

conn.new_state(openconnectionstate)

@staticmethod

def close(conn):

raise runtimeerror('already closed')

class openconnectionstate(connectionstate):

@staticmethod

def read(conn):

print('reading')

@staticmethod

def write(conn, data):

print('writing')

@staticmethod

def open(conn):

raise runtimeerror('already open')

@staticmethod

def close(conn):

conn.new_state(closedconnectionstate)

c = connection()

print(c._state)

c.open()

c.read()

print(c._state)

c.read()

c.write('hello')

c.close()

print(c._state)

------------------------------------------

reading

reading

writing

另一種實現技術涉及對例項的__class__屬性的直接操作:

class connection:

def __init__(self):

self.new_state(closedconnection)

def new_state(self, newstate):

self.__class__ = newstate

def read(self):

raise notimplementederror()

def write(self, data):

raise notimplementederror()

def open(self):

raise notimplementederror()

def close(self):

raise notimplementederror()

class closedconnection(connection):

def read(self):

raise runtimeerror('not open')

def write(self, data):

raise runtimeerror('not open')

def open(self):

self.new_state(openconnection)

def close(self):

raise runtimeerror('already closed')

class openconnection(connection):

def read(self):

print('reading')

def write(self, data):

print('writing')

def open(self):

raise runtimeerror('already open')

def close(self):

self.new_state(closedconnection)

c = connection()

print(c)

c.open()

print(c)

c.close()

print(c)

------------------------------------------

<__main__.closedconnection object at 0x7fd57c2603d0>

<__main__.openconnection object at 0x7fd57c2603d0>

<__main__.closedconnection object at 0x7fd57c2603d0>

這種方案修改類例項的__class__屬性,看似違背了物件導向的基本原則,但從技術上是可行的。此外,由於connection上的所有方法都不再涉及額外的委派步驟,因此這可能會導致**速度更快。

狀態機 狀態機0

近半年都忙於做專案,沒有太多的時間去整理和總結在專案中用過的技術 個人還是覺得技術需要總結提煉和沉澱的,忙到沒時間去總結提公升其實不 是什麼好事,這次講下狀態機,在戰鬥型別的遊戲中角色有多種不同的狀態,而狀態的切換錯綜複雜,23種設計模式中有一種模式叫做狀態模式,不過 這種模式是把狀態切換條件放到各...

python 狀態機 Python 狀態機

class statemachine def init self self.handlers 狀態轉移函式字典 self.startstate none 初始狀態 self.endstate 最終狀態集合 引數name為狀態名,handler為狀態轉移函式,end state表明是否為最終狀態 de...

kanzi狀態機實現

1.在library中選中state managers建立create state manager。2.在library中選中property types建立create property type,name state category custom datatype interger。3.修改s...