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
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
Post a Comment