Unbeknownst to me, Mike was writing a post about the Observer Pattern as the same time as me. His post is part of a series that covers his talk “Design Patterns in JavaScript” from last weekend’s Chicago Code Camp. You should head over and read his post, especially if you work with a lot of JavaScript, but here I’m going to stick to the basics of the pattern—and of course, Ruby.

The Observer Pattern is used when there is an action or series of actions that need to be executed after another action has taken place. For example, let’s say you have an online store and once you’ve changed the price of a particular item to below $10 you need your website to display the price in a bold font (with lots of punctuation and naturally some flash animation), it also needs to be moved to the “bargain” section of your website, and customers who’ve signed up for price alerts need to be notified.

One way to accomplish this would be to load up your item#update method with lots of conditionals and actions that take place once the item hits a certain price threshold. However, this would violate the single responsibility principle and the open-closed principle because each time you needed something else to happen after a price update you’d have to go in and rewrite the method.

Enter the Observer Pattern. What you really need are small classes that execute only after something has changed - the “observers”. Although they are called observers they actually don’t actively do anything. All of the responsibility in this relationship falls on the “subject”- which in the example I started would be the Item. When the price of the item changed it would tell its observers to do whatever they were supposed to do.

And how does the item know about its observers and send them messages? With a simple array and an attr_accessor. Here’s a quick example of an item class with some observers:

class Item
  attr_accessor :description, :price, :observers

  def initialize(price)
    @price = price
    @observers = []
  end

  #...some code for our item...

  def update_price(amount)
    @price = amount
    notify_observers
  end

  def notify_observers
    @observers.each {|observer| observer.commonly_named_method(self)}
  end
end

In order to add and remove observers to an item we could write some methods to shovel new ones into the @observers array:

@observers << NewObserver

or delete them

@observers.delete(observer_to_delete)

However, Ruby has an Observable module you can include on your class that gives you all sorts of goodies. Rather than cover them here I’ll direct you over to the Ruby Docs for a thorough rundown.

Since I happened to read about this wonderful pattern last night I may or may not have seen a nail today. While pairing on a project with Cymen we worked on a method that will generate an invoice, upload a PDF version of that invoice to Amazon S3, and generate and upload PDF’s of all the associated documents with that invoice to S3 as well. Our method started to get pretty heavy so I mentioned the Observer Pattern. There’s a chance we’re going to use it but first we just wanted to make sure that everything worked, and then we’ll check with the rest of the team to see what they think.