I'm currently studying some Design Patterns in Python and tried to implement the State Patter example in the diagram:
It happened to be way more complicated than I expected, I've created a class for each of the four states and the open
and close
methods. To simulate the Open and Close Buttons I uused th pynput
module so I can listen to the keyboard and call the open
and close
and to simulate the open and closed door sensor i just call a sleep
function to wait 3 seconds until the door is closed/open.
I was working ok until i decided to use Threads so the sleep
function call does not block the main program and I could "press button" while the door is closing/opening. Now the state doen't change as it was supposed to. heres the code and an runnong example:
from time import sleep
from pynput import keyboard
from threading import Thread
class Open():
def __init__(self, door):
self.door = door
def __repr__(self):
return 'Open'
def open(self):
pass
def close(self):
print('Closing', end='')
self.door.state = Closing(self)
for _ in range(3):
print('.', end='', flush=True)
sleep(1)
self.door.state = Closed(self)
print('Closed')
class Opening():
def __init__(self, door):
self.door = door
def __repr__(self):
return 'Opening'
def open(self):
pass
def close(self):
print('Opening Interrupted')
self.door.state = Closing(self)
print('Closing', end='')
for _ in range(3):
print('.', end='', flush=True)
sleep(1)
self.door.state = Closed(self)
print('Closed')
class Closed():
def __init__(self, door):
self.door = door
def __repr__(self):
return 'Closed'
def close(self):
pass
def open(self):
print('Openning', end='')
self.door.state = Opening(self)
for _ in range(3):
print('.', end='', flush=True)
sleep(1)
self.door.state = Open(self)
print('Open')
class Closing():
def __init__(self, door):
self.door = door
def __repr__(self):
return 'Closing'
def close(self):
pass
def open(self):
print('Closing Interrupted')
print('Openning', end='')
self.door.state = Opening(self)
for _ in range(3):
print('.', end='', flush=True)
sleep(1)
self.door.state = Open(self)
print('Open')
class ElevatorDoor:
def __init__(self):
self.state = Open(self)
def open(self):
Thread(target=self.state.open).start()
def close(self):
Thread(target=self.state.close).start()
if __name__ == '__main__':
door = ElevatorDoor()
def on_press(key):
global door
if key == keyboard.Key.esc:
return False # stop listener
try:
k = key.char # single-char keys
except Exception:
k = key.name # other keys
if k == 'o':
door.open()
if k == 'c':
door.close()
if k == 's':
print(door.state)
listener = keyboard.Listener(on_press=on_press)
listener.start()
listener.join()
And that is what happens:
<starts script>
<press 'c' key>
Closing...Closed
<press 's' key to check the state>
Closed
<press 'o' key>
Openning...Open
<press 's' key>
Closed
<press 'c' key>
<Nothing happens>
<press 'o' key>
Openning...Open
Any Ideas of what can be going On? Any simpler ways to implement this also are welcome :)
Aucun commentaire:
Enregistrer un commentaire