Skip to content

Instantly share code, notes, and snippets.

@anewusername1
Forked from adomokos/visitor_pattern_example.rb
Created January 18, 2012 17:08
Show Gist options
  • Save anewusername1/1634110 to your computer and use it in GitHub Desktop.
Save anewusername1/1634110 to your computer and use it in GitHub Desktop.
The Visitor Pattern implementation in Ruby from the Wikipedia example
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
class CarElement
# force subclasses to override the accept method
def accept(visitor)
raise NotImpelementedError.new
end
end
class CarElementDoVisitor
def visit(subject)
puts "Do some other visitation: %s" % subject.class.to_s
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 Engine < CarElement
include Visitable # now we have the 'accept' method
end
c = Car.new
c.accept(CarElementPrintVisitor.new) # pass an object that will be visited
c.accept(CarElementDoVisitor.new) # same here
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
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
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment