Skip to content

Instantly share code, notes, and snippets.

@floriandejonckheere
Created April 27, 2017 16:24
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save floriandejonckheere/e0533acde14ba72eb1f4be27b4386c25 to your computer and use it in GitHub Desktop.
Save floriandejonckheere/e0533acde14ba72eb1f4be27b4386c25 to your computer and use it in GitHub Desktop.
Chain of Responsibility
# frozen_string_literal: true
class Handler
attr_accessor :next_handler
def initialize(next_handler = nil)
@next_handler = next_handler
end
def handle(package)
if do_handle package
puts "Handled by #{self.class}"
else
return @next_handler.handle package if @next_handler
puts 'No handlers available'
end
end
end
class SmallDomesticHandler < Handler
def do_handle(package)
return false unless package[:type] == :domestic
return false if package[:weight] > 2
return false if package[:length] > 30
return false if package[:width] > 30
return false if package[:height] > 15
package[:price] = 4.25
# @stamp_chain.handle package
true
end
end
class LargeDomesticHandler < Handler
def do_handle(package)
return false unless package[:type] == :domestic
return false if package[:weight] > 5
return false if package[:length] > 60
return false if package[:width] > 30
return false if package[:height] > 15
package[:price] = 6.75
true
end
end
class EuropeanUnionHandler < Handler
def do_handle(package)
return false unless package[:type] == :european_union
return false if package[:weight] > 10
return false if package[:length] > 80
return false if package[:width] > 60
return false if package[:height] > 100
package[:price] = 10.25
true
end
end
class InternationalHandler < Handler
def do_handle(package)
return false unless package[:type] == :international
return false if package[:weight] > 70
return false if package[:length] > 150
return false if package[:width] > 60
return false if package[:height] > 70
package[:price] = 30
true
end
end
class SmallStampHandler < Handler
def do_handle(package)
loop do
return false if package[:price] < 0.25
package[:price] -= 0.25
package[:stamps] ||= { 0.25 => 0, 0.5 => 0, 1 => 0 }
package[:stamps][0.25] += 1
end
return false
end
end
class MediumStampHandler < Handler
def do_handle(package)
loop do
return false if package[:price] < 0.5
package[:price] -= 0.5
package[:stamps] ||= { 0.25 => 0, 0.5 => 0, 1 => 0 }
package[:stamps][0.5] += 1
end
return false
end
end
class LargeStampHandler < Handler
def do_handle(package)
loop do
return false if package[:price] < 1
package[:price] -= 1
package[:stamps] ||= { 0.25 => 0, 0.5 => 0, 1 => 0 }
package[:stamps][1] += 1
end
return false
end
end
##
# Client
#
chain = SmallDomesticHandler.new(LargeDomesticHandler.new(EuropeanUnionHandler.new InternationalHandler.new))
stamp_chain = LargeStampHandler.new(MediumStampHandler.new SmallStampHandler.new)
package = {
:weight => 1.5,
:length => 26,
:width => 30,
:height => 15,
:type => :domestic
}
puts package
chain.handle package
stamp_chain.handle package
puts "Stamped with #{package[:stamps].sort.collect { |k,v| "#{v} x €#{k}" unless v == 0 }.compact.join ', '}"
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment