An observer pattern application.

Paolino paolo_veronelli at tiscali.it
Thu Aug 18 04:24:59 EDT 2005


Lately I was needing to use multiple inheritance to split behaviour of a 
class and modularize it.
But the problem raises when the need is to add operations to a method 
already present in one of them from another.
I think the technical solution is the use of 'super'.
Then I tried to write a decorator for automatize the 'super' call,but I 
failed.

Next solution is implementing the observer pattern on methods call.
I'm pretty sure there are bugs and ideas to be corrected in the next 
code,any help and comment appreciated.

Regards Paolino

########################################################################################

''' A module collecting classes for known patterns

     '''

import types

class Observer(dict):
   ''' A class defining some decorators for function/methods to 
chain/link them when called .To do:implement pre event execution hooking'''

   def __call__(self,observed,args,kwargs):
     for reaction in self.get(observed,()):
       reaction(*args,**kwargs)

   def emit(self,method,observed=None):
     ''' A decorator for functions to signal their calling.Post hook 
cablated'''
     def wrapper(*args,**kwargs):
       if  observed:
         if type(observed) is types.MethodType:
           event=observed.im_func
         else:
           event=observed
       else:
         event=wrapper
       result=method(*args,**kwargs)
       self(wrapper,args,kwargs)
       return result
     return  wrapper

   def emitOther(self,observed):
     ''' A decorator facility to let the function/method emit another 
event (not itself)'''
     def wrapEmit(method):
       return self.emit(method,observed)
     return wrapEmit

   def reactOn(self,*observeds):
     ''' a decorator to set the function/method as a reaction to 
*observeds event.
         Remember to use __ name mangling when working on methods to be 
able to use
         same reaction name on multiple class inheritances'''
     def reaction(method):
       for observed in observeds:
         if type(observed) is types.MethodType:
           observed=observed.im_func
         self.setdefault(observed,set()).add(method)
       return method
     return reaction


if __name__=='__main__':
   observer=Observer()
   class base(object):
     @observer.emit
     def method(self,*args,**kwargs):
       print '%s.method'%str(self),args,kwargs

   class extensionA(object):
     @observer.reactOn(base.method)
     def __methodReaction(self,*args,**kwargs):
       print 'A,%s.methodReaction'%str(self),args,kwargs

   class extensionB(object):
     @observer.reactOn(base.method)
     def __methodReaction(self,*args,**kwargs):
       print 'B,%s.methodReaction'%str(self),args,kwargs

   class applicable(base,extensionA,extensionB):
     @observer.reactOn(base.method)
     def __methodReaction(self,*args,**kwargs):
       print 'applicable,%s.methodReaction'%str(self),args,kwargs

     pass

   applicable().method('cucu')

		
___________________________________ 
Yahoo! Messenger: chiamate gratuite in tutto il mondo 
http://it.beta.messenger.yahoo.com



More information about the Python-list mailing list