c# - 我如何改进这个价格计算代码,现在进行 4 次计算,但在不久的将来会进行更多计算?

标签 c# design-patterns

我正在尝试找出如何改进我编写的一些代码,这些代码使用一些规则来计算汽车保险的一些不同定价。这是困扰我的部分:

public Insurance GetInsurance(CarData carData)
{
    var insurance = new Insurance();

    insurance.priceGeneral = this.CalculatePrice(new Car { BrandDealer = false, MonthPayment = false, CarData = carData });
    insurance.priceGeneralMonth = this.CalculatePrice(new Car { BrandDealer = false, MonthPayment = true, CarData = carData });
    insurance.priceBrandDealer = this.CalculatePrice(new Car { BrandDealer = true, MonthPayment = false, CarData = carData });
    insurance.priceBrandDealerMonth = this.CalculatePrice(new Car { BrandDealer = true, MonthPayment = true, CarData = carData });

    return insurance;
}

请注意,计算月付款与正常价格(年付款)有很大差异,并且取决于 BrandDealer 是真还是假,也有不同的计算方式。我试图消除这个变量,但客户要求这些规则。

我知道有些属性不是“汽车”的实际属性,但我也会尽快对其进行重构。

我很烦这个计算我做了4次,以后还会有更多的规则。即将到来的新规则将添加另一个 bool 值和另外 2 个计算。

是否有一些我在这里没有发现但应该使用的不错的设计模式?

最佳答案

首先解决你今天遇到的问题,这是一种清理重复计算代码的方法。

首先,我们需要将 Stratgey 模式应用到您的价格计算中,定义计算接口(interface)并将不同的计算逻辑代码移到它们的新位置:

// calculation common interface
public interface IPriceCalculation 
{
   public InsurancePrice CalculatePrice(CarData data);   
}

// result from the calculation
public class InsurancePrice
{
   public string Description { get; set; }
   public decimal Price { get; set; }      
}


// concrete implementations 
public class BrandDealerMonthlyPaymentCalculation : IPriceCalculation
{
   public InsurancePrice CalculatePrice(CarData data)
   {
      // logic to perform calculation of BrandDealer = true, MonthPayment = true

      // just for example...
      return new InsurancePrice() 
      { 
         Description = "Policy price with a Brand dealer and monthly payments",
         Price = 250.25;
      };
   }
}

public class BrandDealerYearlyPaymentCalculation : IPriceCalculation
{
   public InsurancePrice CalculatePrice(CarData data)
   {
      // logic to perform calculation of BrandDealer = true, MonthPayment = false
   }
}

public class NonBrandDealerYearlyCalculation : IPriceCalculation
{
   public InsurancePrice CalculatePrice(CarData data)
   {
      // logic to perform calculation of BrandDealer = false, MonthPayment = false
   }
}

public class NonBrandDealerMonthlyCalculation : IPriceCalculation
{
   public InsurancePrice CalculatePrice(CarData data)
   {
      // logic to perform calculation of BrandDealer = false, MonthPayment = true
   }
}

定义了计算后,您就可以安装它们了。在定义 GetInsurance 方法的类中(我们称之为 InsuranceFactory),我们将在您的 ctor 中执行此操作。这可以通过另一个类通过属性、通过配置、通过 DI 等将它们插入来完成,但是 ctor 是最简单的说明:

public class InsuranceFactory
{
   private List<IPriceCalculation> _priceCalculators = new List<IPriceCalculation>();

   public InsuranceFactory()
   {
      _priceCalculators.Add(new BrandDealerYearlyPaymentCalculation());
      _priceCalculators.Add(new BrandDealerMonthlyPaymentCalculation());
      _priceCalculators.Add(new NonBrandDealerYearlyCalculation());
      _priceCalculators.Add(new NonBrandDealerMonthlyCalculation());
      // easy to add more calculations right here...
   }

}

接下来我们重新访问上面 InsuranceFactory 类中的 GetInsurance 方法:

public Insurance GetInsurance(CarData carData) 
{     
   var insurance = new Insurance();      

   // iterate the different pricing models and them to the insurance policy results

   foreach (IPriceCalculation calculator in _priceCalculators)
   {
      insurance.PriceOptions.Add(calculator.CalculatePrice(carData));
   }

   return insurance; 

} 

注意每次创建新计算时您的 GetInsurance 方法不再需要更改。同样,通过将结果存储在保险对象 (insurance.PriceOptions) 的列表中,您的 Insurance 类也不需要更改。您的 UI 代码可以通过迭代该列表来显示所有选项。这个例子稍微简化了,但应该可以让你继续。

现在谈谈我可以预见的第二个可能的问题。如果你的计算子类开始有额外的排列,你将有一个类爆炸。例如,现在您有 2 个因素(品牌和薪酬计划),每个因素有 2 个选择,给您 2 x 2 = 4 个类别。但是,如果我们将 CreditScore 添加到其中,有 3 个选择(Goor、Fair、Poor)会怎么样。然后你得到:

GoodCreditBrandDealerYearlyPaymentCalculation
GoodCreditBrandDealerMonthlyPaymentCalculation
GoodCreditNonBrandDealerYearlyCalculation
GoodCreditNonBrandDealerMonthlyCalculation
FairCreditBrandDealerYearlyPaymentCalculation
FairCreditBrandDealerMonthlyPaymentCalculation
FairCreditNonBrandDealerYearlyCalculation
FairCreditNonBrandDealerMonthlyCalculation
PoorCreditBrandDealerYearlyPaymentCalculation
PoorCreditBrandDealerMonthlyPaymentCalculation
PoorCreditNonBrandDealerYearlyCalculation
PoorCreditNonBrandDealerMonthlyCalculation

这只会变得更糟。如果它出现,这真的值得自己提问和回答,但这是你应该注意的事情。如果它开始变得像这样,请重构 Calculation 类。但好的是 GetInsurance 中的代码仍然不需要更改。

关于c# - 我如何改进这个价格计算代码,现在进行 4 次计算,但在不久的将来会进行更多计算?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10672491/

相关文章:

C# .net 类型转换问题

java - 面向方面编程中的四人组模式用法?

c++ - 简化类中的 `operatorX` 函数以按给定顺序比较相同类型的属性的正确方法或设计模式?

C#:枚举反模式

c# - 中止阻塞线程的正确方法

C# - 导出 .pfx 证书并稍后将其作为文件导入

c# - 如何访问框架的子元素?

c# - 如何从 C# 获取进程窗口类名?

c++ - 如何使我的工厂的标题不依赖于它创建的模板化对象?

c# - 调用 Actionfilter 时未呈现 _Layout 上的部分 View