[Tutor] Java Observer/Observable type module in Python

Phil Bertram phil.bertram@clear.net.nz
Wed, 28 Feb 2001 08:37:35 +1300

Many thanks. I think I understand.

I was under the impression that the Java Observer classes somehow searched
the memory for any Observerables without any looping and I thought that
would be neat. Sort of 'like magic'. But I guess my thinking was flawed.
Python is definately much easier to understand for a self taught
'programmer' like me as compared to Java.

It seems as though my program already uses the 'Observer' pattern by
updating a Player's score when a team wins a game. In a round about fashion
any way !

I'll get busy tidying things up to follow this pattern a little closer
because it certainly is more elegant than what I have done.

Hopefully substituting 'class Player' for 'class Observer' and 'class Game
for 'class Observable' should do the trick.

>Message: 3
>Date: Mon, 26 Feb 2001 13:39:30 -0500
>From: D-Man <dsh8290@rit.edu>
>To: tutor@python.org
>Subject: Re: [Tutor] Java Observer/Observable type module in Python
>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
>| 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
>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.