使用不同数据进行计算的计费模型的策略模式?

发布于 2024-08-13 10:01:41 字数 1005 浏览 1 评论 0原文

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

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

每次展示费用的计算很简单:展示次数 X 每次展示费用

电话查询的计算稍微复杂一些:通话次数 X 每次通话费用

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 秒,我需要编写一个新策略。解决这个问题的最佳设计选择是什么?

We have an invoice model that bills clients in a few different ways. For the sake of brevity, I'm going to focus on two: cost per impression and cost per phone inquiry. My thought was to implement these (and the rest) as strategies and then dynamically mix them into the invoice class.

This seems appropriate because there are different sources of information used to determine the number of impressions/calls. This could be encapsulated in the strategy, while keeping the basic formula in the Invoice class.

The calculation for cost per impression is simple: num impressions X cost per impression.

The calculation for phone inquiries is a little more complicated: 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

Then, the modules could be:

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

However, whether a call counts or not is based on the length of the call and this varies from model to model. Thus, when I'm searching through the phone logs I need to have this value.

My question is where does this value get stored? I could create a strategy for invoices that are based on 10 second calls and a separate one for 30 second ones, but that seems wasteful. If a deal came in that wants the threshold to be 15 seconds, I need to write a new strategy. What is the best design choice to solve this issue?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

撩人痒 2024-08-20 10:01:41

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

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

Don't implement your strategies as module mixins. Implement them as full fledged classes with a public PerInquiryCalculation method and inject the right one into the Invoice class using its constructor.

This way each strategy class can have its own state variables set during construction. The constructor of PerInquiryStrategy can take a duration threshold that the PerInquiryCalculation method uses to calculate the fees.

夏夜暖风 2024-08-20 10:01:41

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

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

You can retrieve all mixed modules and base class using the class method ancestors. So if you have an instance myInvoice, you can simply use myInvoice.class.ancestors. It returns an array of constants so you can check for inclusion.

BTW, in this context, I think that traditional composition/aggregation is more appropriate in this case: it is safer when several different strategy coexists at the same time. You do not want ending in changing all invoices strategy because you affected the base class...

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文