Problem:
Programming model that uses observer pattern, where an object(subject) maintains bunch of observers and send different types of notifications to bunch of observers
Solution:
#subject.py
"""
An object called subject,
1) Maintains the list of dependents, called observers
2) Automatically notifies observers, about different type of events
"""
import random
import threading
import time
from eventloop import eventLoop
import pdb
def generateEventHelper(eventLoop):
for i in range(10):
time.sleep(random.random())
eventLoop.sendEvent('data', i+random.random())
print('Event sent')
eventLoop.sendEvent('done')
def launchThreadHelper(eventLoop):
t = threading.Thread(target=generateEventHelper, args=(eventLoop, ))
t.start()
# action code for a specific event
acc = 0
def addToAccAction(e, eventLoop): # Not sure, how to avoid 2nd arg
global acc
global numOfEvents
acc += e[1]
print(acc)
# action code for done event
doneEvents = 0
def shutDownAction(e, eventLoop):
global doneEvents
doneEvents += 1
if doneEvents == 4: # After 4 done events
print('Event loop is shutting down')
eventLoop.shutDown()
def subject():
# Add observer, in this case
eventLoop.addEventListener( lambda x: x[0] == 'data',
addToAccAction)
eventLoop.addEventListener( lambda x: x[0] == 'done',
shutDownAction)
# Now generate events - can be data or state or whatever
launchThreadHelper(eventLoop)
launchThreadHelper(eventLoop)
launchThreadHelper(eventLoop)
launchThreadHelper(eventLoop)
# Notifying those events to relevant observers
eventLoop.runLater(2, lambda: print('2 seconds are up***********************'))
eventLoop.runForever()
# pdb.set_trace()
if __name__ == '__main__':
subject()
#eventloop.py
"""
EventLoop help subject,
1) to maintain the observers
2) to notify observers
3) to process different types of events
"""
import queue
import time
class EventLoop():
def __init__(self):
self.events = queue.Queue()
self.observers = []
self.timedCallbacks = []
self.pleaseShutDown = False
self.startTime = None
def sendEvent(self, *args):
self.events.put(args)
print('Got an event') # Debugging
def runForever(self):
while True:
e = self.events.get()
self.processEvent(e)
if self.pleaseShutDown:
break
now = time.time()
toRun = [(t,cb) for (t, cb) in self.timedCallbacks if t < now]
for t, cb in toRun:
if t < now:
cb()
self.timedCallbacks.remove((t,cb))
def runLater(self, when, callback):
self.timedCallbacks.append((time.time() + when, callback))
def processEvent(self, e):
for pred, action in self.observers:
if pred(e):
action(e, self)
def shutDown(self):
self.pleaseShutDown = True
def addEventListener(self, predicate, action):
self.observers.append((predicate, action))
# Singleton
eventLoop = EventLoop() # To maintain observers and notify them
Question:
All event types & observers(ex: addToAccAction) are scattered in subject.py, Please suggest a design pattern to add new event types and observers
Aucun commentaire:
Enregistrer un commentaire