Skip navigation

Recently, I decided to take quick read of the Russ Olsen’s Design Patterns in Ruby just in case the book had interesting ways of solving common problems. The book tends to digress into type safety (the lack of it) and other gizmoz that Rubyists defend and evangelize. Hence, I decided to write this article that will simply show you the code for the most important patterns. I have just covered the most elegant way these can be used. For what its worth, this is really the only reason you would want to read this book.

Having said that, I assume that you can take a judgement on when these patterns are to be used. That will truly determine whether/if it solves a problem for you. This post is just about doing it the Ruby way.

Template Method

Wiki Link. This pattern is among the oldest ones and has inherent support in most language constructs(Java interfaces )

class Bird
  def chirp
    raise "I dont know how to chirp. I only know that  bird must chirp"
  end
end

class Duck < Bird
  def chirp
    puts "quack"
  end
end

Duck.new.chirp # quack

Strategy

Wiki Link

The most obvious problem with the above implementataion arises when learn from Darwinian theory that Ducks may not just quack but may speak too.

class BirdShout
  def chirp
    raise "I dont know what to do"
  end
end

class Quack < BirdShout
  def chirp
    puts "Quack"
  end
end

class Tweet < BirdShout
  def chirp
    puts "I thought I taw a putty tat"
  end
end

class Duck
  def initialize strategy
    @chirper = strategy
  end

  def chirp
    @chirper.chirp
  end
end

Duck.new(Quack.new).chirp #Quack
Duck.new(Tweet.new).chirp #I thought I taw a putty tat

The base class in this example is clearly optional (It can be removed from the code literally along with the subclass constructs with little consequence). In a duck typed language like Ruby, a base class default implementation is asymmetric with the rest of the language’s philosophy.

This can be however had for those of you are still insecure about Ruby ‘s type system.
This can also be implemented using ruby’s Proc objects:

class Duck
  def initialize(&strategy)
    @chirper = strategy
  end

  def chirp
    @chirper.call
  end
end

Duck.new{puts "Quack"}.chirp

The observer

Ruby constructs do not significantly influence this pattern. Wiki Link

class CompanyStock
  attr_accessor :price

def initialize
    @observers = []
  end

  def add_observer observer
    @observers << observer
end

  def price= new_price
    unless price == new_price
      @price = new_price
      notify_observers
    end
  end

  def notify_observers
    @observers.each do |o|
      o.notify(self)
    end
  end
end

class PotentialBuyer
  def notify stock
    puts stock.price
  end
end

class PotentialSeller
  def notify stock
    puts stock.price
  end
end

stock = CompanyStock.new
stock.add_observer(PotentialBuyer.new)
stock.add_observer(PotentialSeller.new)
stock.price = 10

One sizable influence Ruby can have is, instead of passing the Observer objects, we could pass in Observer code blacks with the CompanyStock’s notify method invoking a “call” on the procs to notify.


Advertisements

One Trackback/Pingback

  1. […] Part1 Composite Pattern […]

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: