Implementing the Visitor Pattern in Ruby - with reusable Modules

The Visitor pattern is useful, where you want to perform two or more operations over a hierachy of heterogeneous objects, and want to avoid having to implement the operation on each and every class in the hierarchy.

It is especially useful, if you think you will be adding more operations in the near future.

An example here is for different kinds of waiters, visiting different kinds of tables.
A real programming example, might be different kinds of parsing operations being performed on elements of a document.

The Visitor Pattern is a little tricky to implement, as it involves double despatch (Visitor sends message to Visitee, and Visitee then sends appropriate message to the Visitor).

In Ruby, we can write two small modules which make it really easy to implement this pattern.


The modules:

module VisitorBase
  def do_visit object
    object.accept(self)
  end
end


module Visitable
  def accept visitor
    visitor.send 'visit_' + self.class.name, self
  end
end

Creating a Visitor:

require "visitor_base"


class CountingWaiter
  include VisitorBase


  attr_reader :total_num_diners


  def initialize
    @total_num_diners = 0
  end


  def visit_Table table
    @total_num_diners += table.num_diners
  end


  def visit_DutchTable dutch_table
    @total_num_diners += dutch_table.aantal_gasten
  end


end


Making a class Visitable:

require "visitable"

class DutchTable
  include Visitable
...
end

No need to write any accept() methods - the correct visitor.visit_() method will automatically be generated by the module Visitable !

Comments