2009-12-03 55 views
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秒,则需要编写新策略。解决此问题的最佳设计选择是什么?

回答

0

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

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

3

请勿将您的策略​​实现为模块mixins。使用公开的PerInquiryCalculation方法将它们作为完整的类实现,并使用其构造函数将正确的类注入Invoice类。

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