Skip to content

Instantly share code, notes, and snippets.

@RedFred7
Created February 11, 2015 20:39
Show Gist options
  • Save RedFred7/2809a0410ec452b64f4d to your computer and use it in GitHub Desktop.
Save RedFred7/2809a0410ec452b64f4d to your computer and use it in GitHub Desktop.
Design Patterns the Ruby way: strategy
####### STRATEGY PATTERN #############
### way #1
## The following code implements the strategy pattern in the traditional
## manner, i.e. with a separate class for each strategy (xxxPayment),
## which is then passed in the constructor of the Context class (in
## this case the Purchase class). The Context then selects a strategy
## at construction time and delegates its stragegy method (i.e. pay) to
## the strategy object
# this abstract base class is un-necessary in Ruby
# class PaymentStrategy
# def pay(sum)
# raise "can't call that!"
# end
# end
class PayPalPayment #< PaymentStrategy
def pay(sum)
puts ".....paying $#{sum} by PayPal"
end
end
class WorldPayPayment #< PaymentStrategy
def pay(sum)
puts ".....paying $#{sum} by WorldPay"
end
end
class BitcoinPayment #< PaymentStrategy
def pay(sum)
puts ".....paying $#{sum} by Bitcoin"
end
end
class Purchase
attr_reader :items, :sum
attr_accessor :payment_method
def initialize(items, payment_method)
@payment_method = payment_method
@sum = 0
items.each do |item, value|
@sum += value
end
end
def pay
payment_method.pay(@sum)
end
end
puts "####### way 1"
purchase = Purchase.new({cd_Wild_Beasts: 5.2, baseball_cap: 8.5 }, WorldPayPayment.new)
purchase.pay
### way #2
## This is the re-work of the pattern using code blocks (a.k.a lambdas)
## to dynamically define our strategy. We have no more need of Strategy
## objects, as we create our strategy dynamically in a code block, when
## we create the Purchase object. This is a much more flexible and scalable
## way of implementing the Strategy pattern.
class Purchase
attr_reader :items, :sum
attr_accessor :payment_method
def initialize(items, &payment_method)
@payment_method = payment_method
@sum = 0
items.each do |item, value|
@sum += value
end
end
def pay
payment_method.call(@sum)
end
end
puts "####### way 2"
purchase = Purchase.new({cd_Wild_Beasts: 5.2, baseball_cap: 8.5 }) {|sum| puts ".....paying $#{sum} by WorldPay"}
purchase.pay
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment