Brian Palmer wrote: > I know you can emulate sending different messages using the 'observer' > standard library, but I've never felt that approach was natural, and I > haven't found a general-purpose Observer Pattern library that fits me, > so I've been working on my own approach (borrowing heavily from C#). > I'm still pretty ruby-nuby, though, so I'm looking for > suggestions/improvements. Anyone have any thoughts? You might find http://redshift.sourceforge.net/observable interesting. I should have called it "observable attribute", because observations occur in the context of an attr of an object rather than the whole object. Assignments to attrs trigger code in observers, if the assigned value matches a pattern (and is not == the old value). It was specifically designed for GUI code (Fox in particular). For instance, a dialog with some controls gets wired up to another window with display objects so that the controls stay in sync with the objects. One limitation, in comaprison with your idea: you can't add unlimited observer code--you can only add one observer per observing object, per pattern. (Each observable attr has a hash that maps [observer, pattern] => proc.) I tend to think this is sensible, but YMMV. Here's how your example would look with observable attrs: require 'observable' class TextBox extend Observable observable :text def initialize txt = "" self.text = txt end def key=(k) # Assume keypress is an instantaneous event, so don't assign. We # can still observe the event. end observable :key # Do this after defining #key= so that the no-op behavior above # is retained. The #key= method defined by observable will first # call the pre-existing #key= method (no-op, in this case), then # notify observers. end def my_key_press(k) puts "KEY: #{k}" end box = TextBox::new box.when_text // do puts "Text changed!" end box.when_key // do |k| my_key_press(k) end # The pattern matching uses #===, so patterns can be regexes, # classes, etc. puts "---" box.text = "New text!" puts "---" box.key = 'j' box.key = 'j' p box.key puts "---" box.cancel_when_key //, self # self is the observer box.key = 'k' # no effect puts "---" box.when_text /42/ do puts "The answer!" end box.text = "42" __END__ Output: Text changed! --- Text changed! --- KEY: j KEY: j nil --- --- Text changed! The answer!