[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
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