[Tutor] Java Observer/Observable type module in Python
D-Man
dsh8290@rit.edu
Mon, 26 Feb 2001 13:39:30 -0500
On Tue, Feb 27, 2001 at 06:51:01AM +1300, Phil Bertram wrote:
| Hi all
|
| I was reading some Java info and came across the Observer and Observable
| classes which appear to work together to communicate changes in an object's
| state to one or many other objects.
|
| Is there a similar feature in Python ?
This can be done with (almost) any language. The Observer pattern
actually comes from "Design Patterns" by the Gang of Four, with the
example being in C++. (or Smalltalk, they used both languages in the
book)
class Observer :
def changed( self , observable ) :
print "%s has changed" % str( observable )
class Observable :
def __init__( self , init_value ) :
self.observers = []
self.value = init_value
def __str__( self ) :
return "Observable %d : %s" % id( self ) , self.value
def add_observer( self , observer ) :
self.observers.append( observer )
def remove_observer( self , observer ) :
self.observer.remove( observer )
def _notify_of_change( self ) :
for observer in self.observers :
observer.changed( self )
def mutator_function_that_changes_self( self , new_value ) :
self.value = new_value
self._notify_of_change()
# test my code :
if __name__ == "__main__" :
observer1 = Observer()
observer2 = Observer()
observable = Observable( 13 )
observable.add_observer( observer1 )
observable.add_observer( observer2 )
observable.mutator_function_that_changes_self( 50 )
observable.remove_observer( observer1 )
observable.mutator_function_that_changes_self( 20 )
observable.remove_observer( observer2 )
BTW, I just wrote this and haven't tested it so if something looks
ridiculously stupid, I probably made a mistake. Also, instead of
using a list in the Observable class, a dictionary could be used to
improve performance on adding/removing observers. This would require
that the observers be hashable. Using a list like this makes the
order the observers recieve notification the same as the order they
registered themselves. A dictionary wouldn't allow this.
Java provides classes/interfaces in the standard library called
Observer and Observable that implement this pattern in a very basic
way. The main need for this in Java is its static type checking and
inablility to pass function "pointers" (pointers in C/C++, objects in
Python) so the Observable must know the name of the method to call in
the Observer. AFIAK Swing doesn't use those classes (maybe part of
the implementation, I don't know) but it uses the Observer Pattern
heavily. Since you are using Python, you can just create the
Observer/Observable interfaces you need when you need them and make
the suitable for that particular task, rather than trying to make a
generalized implementation. Also, you could choose to accept a
function object in the add_observer function, instead of an Observer
object allowing clients to determine exactly which function will get
the notification. (A la gtk--, the C++ bindings for the GTK+ toolkit)
This is my preferred mechanism for listening for GUI events.
HTH,
-D