我在遗留系统中有一个看起来像这样的模型:
class Prize < ActiveRecord::Base
def win
# do a bunch of things
end
end
我们从一个奖品开始,但与其他任何奖品一样,我们正在处理的奖品类型也开始扩大。所以现在 def win 正在做一大堆案例/转换来决定奖品类型。
出于这个原因,我决定这样做:
class DailyPrize < Prize
def win
#do only daily prize stuff, no type checking.
end
end
这段代码在我们将其发送给 QA 之前正在接受审查,现在我被要求使用组合(mixin)而不是子类来执行此操作。我想不出一个干净的方法来做到这一点。
遗留代码库在很多地方执行以下操作,我不想到处更改内容:
prize = 奖品.new 获奖.win
那么,我的问题是如何使用组合实现这一点?
最佳答案
这是我通过组合而非继承替换您的代码的理解。
class Prize < ActiveRecord::Base
def prize
@prize ||= PrizeFactory.build(self)
end
def win
prize.win
end
end
class PrizeFactory
def self.build(prize)
if prize.daily?
DailyPrize.new(prize)
# other condition to build specific prize
end
end
end
class DailyPrize
def initialize(prize)
@prize = prize
end
def win
#do only daily prize stuff
#access @prize to get @prize attribute
#if you use it, you have coupling (see below)
end
end
问题是,这可能并不比您的实现更好,它实际上取决于您在领域逻辑方面取得的成就。
使用组合,一个目标是减少对象之间的耦合,如果你调用了很多 @prize
DailyPrice
中的对象方法win
方法,你在这两个类之间有一个紧密的耦合,你可能会失去组合的好处。
关于ruby-on-rails - 在 Rails 中将继承转换为组合,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13571076/