3

我们有一个发票模型,可以通过几种不同的方式向客户收费。为简洁起见,我将重点关注两个:每次展示费用和每次电话查询费用。我的想法是将这些(以及其他)作为策略实现,然后将它们动态地混合到发票类中。

这似乎是合适的,因为有不同的信息来源用于确定展示次数/调用次数。这可以封装在策略中,同时将基本公式保留在Invoice类中。

每次展示费用的计算很简单:num impressions X cost per impression

电话查询的计算稍微复杂一些:num calls X cost per call.

class Invoice
  def self.strategy
    self.class_eval <<-EOS
    include #{billing_type}
    EOS
  end

  def invoice_amount
    # this will used the module mixed in above
    self.rate * calculate_impressions
  end
end

然后,模块可以是:

module PerImpressionCalculation
  def calculate_impressions
     # get the number of impessions from source a...
  end
end

module PerInquiryCalcuation
  def calculate_impressions
     # get the number of impessions from source b...
  end
end

但是,通话是否重要取决于通话的时长,这因型号而异。因此,当我搜索电话日志时,我需要有这个值。

我的问题是这个值存储在哪里?我可以为基于 10 秒调用的发票创建一个策略,并为 30 秒调用一个单独的发票,但这似乎很浪费。如果达成的交易希望阈值为 15 秒,我需要编写一个新策略。解决这个问题的最佳设计选择是什么?

4

2 回答 2

3

不要将您的策略​​实现为模块混合。使用公共方法将它们实现为成熟的类,并使用其构造函数PerInquiryCalculation将正确的类注入到类中。Invoice

这样,每个策略类都可以在构造过程中设置自己的状态变量。的构造函数PerInquiryStrategy可以采用该PerInquiryCalculation方法用于计算费用的持续时间阈值。

于 2009-12-04T05:25:50.370 回答
0

您可以使用类方法检索所有混合模块和基类ancestors。所以如果你有一个实例myInvoice,你可以简单地使用myInvoice.class.ancestors. 它返回一个常量数组,以便您检查是否包含。

顺便说一句,在这种情况下,我认为传统的组合/聚合在这种情况下更合适:当几种不同的策略同时共存时更安全。您不希望以更改所有发票策略结束,因为您影响了基类......

于 2009-12-03T07:43:16.397 回答