Files
python3-cookbook/cookbook/c08/p19_stateful_object.py
2015-02-05 15:39:40 +08:00

150 lines
2.9 KiB
Python

#!/usr/bin/env python
# -*- encoding: utf-8 -*-
"""
Topic: 实现状态对象或状态机
Desc :
"""
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'
class Connection1:
"""新方案——对每个状态定义一个类"""
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 = Connection1()
print(c._state)
c.open()
# Alternative implementation
class State:
def __init__(self):
self.new_state(State_A)
def new_state(self, state):
self.__class__ = state
def action(self, x):
raise NotImplementedError()
class State_A(State):
def action(self, x):
# Action for A
pass
self.new_state(State_B)
class State_B(State):
def action(self, x):
# Action for B
pass
self.new_state(State_C)
class State_C(State):
def action(self, x):
# Action for C
pass
self.new_state(State_A)