
代码示例:
以下是关于 Ruby 中 Strategy 策略模式的详细实例解析:
实例一:报告生成器
背景:假设有一个 ReportGenerator 类,需要生成多种格式的报告,如 JSON、HTML 和纯文本格式。
代码实现:
require 'json'
module ReportFormatters
class JSON
def self.format(data)
data.to_json
end
end
class PlainText
def self.format(data)
data.to_s
end
end
class HTML
def self.format(data)
html = "<html><body><ul>"
data.each { |product, amount| html << "<li>#{product}: #{amount}</li>" }
html << "</ul></body></html>"
end
end
end
class ReportGenerator
def self.generate(data, formatter)
formatter.format(data)
end
end
data = { onions: 31, potatoes: 24, eggs: 10 }
puts ReportGenerator.generate(data, ReportFormatters::HTML)
puts ReportGenerator.generate(data, ReportFormatters::JSON)
puts ReportGenerator.generate(data, ReportFormatters::PlainText)
解析:
- 策略接口:这里通过模块
ReportFormatters中的各个类来定义不同的格式化策略,每个策略类都有一个format方法,这相当于策略接口。 - 上下文:
ReportGenerator类作为上下文,它接受一个格式化策略,并调用该策略的format方法来生成报告。 - 优点:当需要添加新的报告格式时,只需新增一个策略类,无需修改
ReportGenerator类,符合开闭原则。
实例二:购物车支付
背景:一个 ShoppingCart 类,需要支持多种支付方式,如信用卡支付和 PayPal 支付。
代码实现:
module PaymentStrategy
def pay(amount)
raise NotImplementedError, 'Payment method not implemented'
end
end
class CreditCardStrategy
include PaymentStrategy
def initialize(card_number)
@card_number = card_number
end
def pay(amount)
puts "Paid #{amount} using Credit Card: #{@card_number}"
end
end
class PayPalStrategy
include PaymentStrategy
def initialize(email)
@user_email = email
end
def pay(amount)
puts "Paid #{amount} using PayPal: #{@user_email}"
end
end
class ShoppingCart
attr_accessor :strategy
def initialize(strategy = nil)
@strategy = strategy
end
def set_payment_strategy(strategy)
@strategy = strategy
end
def checkout(amount)
@strategy.pay(amount)
end
end
# 使用示例
cart = ShoppingCart.new
cart.set_payment_strategy(CreditCardStrategy.new('1234567890'))
cart.checkout(100)
cart.set_payment_strategy(PayPalStrategy.new('user@example.com'))
cart.checkout(200)
解析:
- 策略接口:通过模块
PaymentStrategy定义了一个pay方法,作为所有支付策略的共同接口。 - 具体策略:
CreditCardStrategy和PayPalStrategy类分别实现了具体的支付逻辑。 - 上下文:
ShoppingCart类作为上下文,它持有一个支付策略对象的引用,并在需要时调用该策略的pay方法来完成支付。 - 优点:购物车类无需关心具体的支付细节,只需通过策略对象来完成支付。当需要添加新的支付方式时,只需新增一个策略类即可。
实例三:税收计算
背景:不同国家的税收计算规则不同,需要根据国家来计算净工资。
代码实现:
class UkraineTaxes
def self.taxes(amount)
(amount * 0.05) + 313
end
end
class PolandTaxes
def self.taxes(amount)
amount * 0.3
end
end
class UsTaxes
def self.taxes(amount)
(amount * 0.2) + 100
end
end
class Taxes
def initialize(amount)
@amount = amount
@strategies = {
'Ukraine' => UkraineTaxes.method(:taxes),
'Poland' => PolandTaxes.method(:taxes),
'U.S.' => UsTaxes.method(:taxes)
}
end
def net_salary(country)
strategy = @strategies[country]
strategy ? @amount - strategy.call(@amount) : @amount
end
end
# 使用示例
taxes = Taxes.new(1200)
puts taxes.net_salary('U.S.') # => 700.0
puts taxes.net_salary('Ukraine') # => 637.0
解析:
- 策略接口:通过各个国家的税收类(如
UkraineTaxes、PolandTaxes等)定义了taxes方法,作为税收计算的策略接口。 - 上下文:
Taxes类作为上下文,它持有一个策略映射表,并根据国家选择对应的策略来计算净工资。 - 优点:将不同国家的税收计算逻辑封装在各自的策略类中,主逻辑类
Taxes不需要关心具体的计算细节,只需调用相应的策略即可。当需要添加新的国家税收规则时,只需新增一个策略类并
更多技术文章见公众号: 大城市小农民

1080

被折叠的 条评论
为什么被折叠?



