W3Cschool
恭喜您成為首批注冊用戶
獲得88經(jīng)驗值獎勵
你想實現(xiàn)一個狀態(tài)機或者是在不同狀態(tài)下執(zhí)行操作的對象,但是又不想在代碼中出現(xiàn)太多的條件判斷語句。
在很多程序中,有些對象會根據(jù)狀態(tài)的不同來執(zhí)行不同的操作。比如考慮如下的一個連接對象:
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'
這樣寫有很多缺點,首先是代碼太復(fù)雜了,好多的條件判斷。其次是執(zhí)行效率變低,因為一些常見的操作比如read()、write()每次執(zhí)行前都需要執(zhí)行檢查。
一個更好的辦法是為每個狀態(tài)定義一個對象:
class Connection1:
"""新方案——對每個狀態(tài)定義一個類"""
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()
>>> c._state
<class '__main__.ClosedConnectionState'>
>>> c.read()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "example.py", line 10, in read
return self._state.read(self)
File "example.py", line 43, in read
raise RuntimeError('Not open')
RuntimeError: Not open
>>> c.open()
>>> c._state
<class '__main__.OpenConnectionState'>
>>> c.read()
reading
>>> c.write('hello')
writing
>>> c.close()
>>> c._state
<class '__main__.ClosedConnectionState'>
>>>
如果代碼中出現(xiàn)太多的條件判斷語句的話,代碼就會變得難以維護(hù)和閱讀。這里的解決方案是將每個狀態(tài)抽取出來定義成一個類。
這里看上去有點奇怪,每個狀態(tài)對象都只有靜態(tài)方法,并沒有存儲任何的實例屬性數(shù)據(jù)。實際上,所有狀態(tài)信息都只存儲在 Connection
實例中。在基類中定義的 NotImplementedError
是為了確保子類實現(xiàn)了相應(yīng)的方法。這里你或許還想使用8.12小節(jié)講解的抽象基類方式。
設(shè)計模式中有一種模式叫狀態(tài)模式,這一小節(jié)算是一個初步入門!
Copyright©2021 w3cschool編程獅|閩ICP備15016281號-3|閩公網(wǎng)安備35020302033924號
違法和不良信息舉報電話:173-0602-2364|舉報郵箱:jubao@eeedong.com
掃描二維碼
下載編程獅App
編程獅公眾號
聯(lián)系方式:
更多建議: