1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| class Connection: def __init__(self): self.state = 'CLOSED' def read(self): if self.state != 'OPEN': raise RuntimeError('Not open') print('reading') def write(self): 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'
|
这样很不优雅,而且包含了大量重复的代码。
我们的目的是进行状态判断,那么我们本就可以把OPEN跟CLOSE状态各自封装成一个类。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66
| 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() 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) class Connection: def __init__(self): self.new_state(ClosedConnectionState) def new_state(self, newstate): self._state = newstate 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) if __name__ == '__main__': c = Connection() print(c) try: c.read() except RuntimeError as e: print(e) c.open() print(c) c.read() c.close() print(c)
|
这里的每种状态都用类和静态方法来实现,在每个静态方法中都把Connection类的实例作为第一个参数。这是因为我们在不同的状态类中不保存任何实例数据,所有的实例数据都应该保存在Connection实例中。
再看看第二种方法,直接修改实例的class属性
这里不再将Connection和COnnectionState作为单独的类来实现,现在我们将他们合并在一起。随着状态的改变,实例也会修改自己的类型。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43
| class Connection: def __init__(self): self.new_state(ClosedConnection) def new_state(self, state): self.__class__ = state 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) if __name__ == '__main__': c = Connection() print(c) try: c.read() except RuntimeError as e: print(e) c.open() print(c) c.read() c.close() print(c)
|
聪明的同学可能会看出,这TM就是设计模式中的状态模式嘛。