public
Created — forked from adomokos/visitor_pattern_example.rb

The Visitor Pattern implementation in Ruby from the Wikipedia example

  • Download Gist
body.rb
Ruby
1 2 3
class Body < CarElement
include Visitable # now we have the 'accept' method
end
car.rb
Ruby
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
class Car < CarElement
def initialize
# Here we build an array of objects that will be visited. This can be done
# after initialize as well; it just needs to be built before calling 'accept'.
@elements = []
@elements << Wheel.new("front left")
@elements << Wheel.new("front right")
@elements << Wheel.new("back left")
@elements << Wheel.new("back right")
@elements << Body.new
@elements << Engine.new
end
 
# go through each element and 'visit' it
def accept(visitor)
@elements.each do |element|
element.accept(visitor)
end
visitor.visit(self)
end
end
car_element.rb
Ruby
1 2 3 4 5 6
class CarElement
# force subclasses to override the accept method
def accept(visitor)
raise NotImpelementedError.new
end
end
car_element_do_visitor.rb
Ruby
1 2 3 4 5
class CarElementDoVisitor
def visit(subject)
puts "Do some other visitation: %s" % subject.class.to_s
end
end
car_element_print_visitor.rb
Ruby
1 2 3 4 5 6 7
# Each of the following classes visit the objects, doing something different
# each time.
class CarElementPrintVisitor
def visit(subject)
puts "Visiting: %s" % subject.class.to_s
end
end
engine.rb
Ruby
1 2 3
class Engine < CarElement
include Visitable # now we have the 'accept' method
end
implementation.rb
Ruby
1 2 3
c = Car.new
c.accept(CarElementPrintVisitor.new) # pass an object that will be visited
c.accept(CarElementDoVisitor.new) # same here
single_file_visitor_pattern_example.rb
Ruby
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87
class CarElement
# force subclasses to override the accept method
def accept(visitor)
raise NotImpelementedError.new
end
end
 
module Visitable
# Accept a visitor object. This will be visited, meaning its 'visit' method
# will be invoked
def accept(visitor)
visitor.visit(self)
end
end
 
class Wheel < CarElement
include Visitable # now we have the 'accept' method
 
attr_reader :name
def initialize(name)
@name = name
end
end
 
class Engine < CarElement
include Visitable # now we have the 'accept' method
end
 
class Body < CarElement
include Visitable # now we have the 'accept' method
end
 
class Car < CarElement
def initialize
# Here we build an array of objects that will be visited. This can be done
# after initialize as well; it just needs to be built before calling 'accept'.
@elements = []
@elements << Wheel.new("front left")
@elements << Wheel.new("front right")
@elements << Wheel.new("back left")
@elements << Wheel.new("back right")
@elements << Body.new
@elements << Engine.new
end
 
# go through each element and 'visit' it
def accept(visitor)
@elements.each do |element|
element.accept(visitor)
end
visitor.visit(self)
end
end
 
# Each of the following classes visit the objects, doing something different
# each time.
class CarElementPrintVisitor
def visit(subject)
puts "Visiting: %s" % subject.class.to_s
end
end
 
class CarElementDoVisitor
def visit(subject)
puts "Do some other visitation: %s" % subject.class.to_s
end
end
 
c = Car.new
c.accept(CarElementPrintVisitor.new) # pass an object that will be visited
c.accept(CarElementDoVisitor.new) # same here
 
# OUTPUT
# Visiting: Wheel
# Visiting: Wheel
# Visiting: Wheel
# Visiting: Wheel
# Visiting: Body
# Visiting: Engine
# Visiting: Car
# Do some other visitation: Wheel
# Do some other visitation: Wheel
# Do some other visitation: Wheel
# Do some other visitation: Wheel
# Do some other visitation: Body
# Do some other visitation: Engine
# Do some other visitation: Car
visitable.rb
Ruby
1 2 3 4 5 6 7
module Visitable
# Accept a visitor object. This will be visited, meaning its 'visit' method
# will be invoked
def accept(visitor)
visitor.visit(self)
end
end
wheel.rb
Ruby
1 2 3 4 5 6 7 8
class Wheel < CarElement
include Visitable # now we have the 'accept' method
 
attr_reader :name
def initialize(name)
@name = name
end
end

Please sign in to comment on this gist.

Something went wrong with that request. Please try again.