在方法中应用开/关原理

时间:2013-04-19 11:33:12

标签: c# design-patterns solid-principles

您好我的任务是重构一部分代码,以便它与开放/封闭原则相对应。我设法在两种方法中应用策略模式但在一种方法中我不知道应该如何应用继续进行。

public ProductPriceCalculator(Product product)
{
    this.product = product;
    buyerStrategy = new BuyerStrategy();
    discountStrategy = new DiscountStrategy();
}

public Price CalculatePrice()
{
    price = new Price();

    decimal productPrice = product.BasePrice + 
                           (product.BasePrice * product.Addition);
    decimal TVA = CalculateTVA();
    price.ProductPrice = productPrice*TVA;
    decimal discount = CalculateDiscount(price.ProductPrice);
    price.Discount = price.ProductPrice * discount;
    price.ProductPriceWithDiscount = price.ProductPrice - price.Discount;
    price.TransportPrice = product.Transport.GetTransportPrice();
    price.TotalPrice = price.ProductPriceWithDiscount + price.TransportPrice;

    return price;
} 

在这种情况下,这个方法通过使用类中的方法来初始化对象。因为它代表这个方法没有关闭进行修改,因为如果在某些时候我必须添加另一个属性到Price我将不得不回到这里初始化它。

如何正确构建此代码?

2 个答案:

答案 0 :(得分:5)

一种可能的解决方案如下:

 public class ProductPriceCalculator
 {
    private readonly Product _product;
    private readonly BuyerStrategy _buyerStrategy;
    private readonly DiscountStrategy _discountStrategy;
    private readonly Price _price;

    public ProductPriceCalculator(Product product,BuyerStrategy buyerStrategy,DiscountStrategy discountStrategy,Price price)
    {
        _product = product;
        _buyerStrategy = buyerStrategy;
        _discountStrategy = discountStrategy;
        _price = price;
    }

    public Price CalculatePrice()
    {
        decimal productPrice = _product.BasePrice + (_product.BasePrice * _product.Addition);
        decimal TVA = CalculateTVA();
        decimal discount = CalculateDiscount(productPrice * TVA);
        decimal transportPrice = _product.Transport.GetTransportPrice();

        return _price.CalculatePrice(productPrice*TVA,discount,transportPrice);
    }

    ...

 }

public class Price
{
    ...

    public virtual Price CalculatePrice(decimal productPrice, decimal discount, decimal transportPrice)
    {
        Price price = new Price();

        price.ProductPrice = productPrice;
        price.Discount = ProductPrice * discount;
        price.ProductPriceWithDiscount = ProductPrice - Discount;
        price.TransportPrice = transportPrice;
        price.TotalPrice = ProductPriceWithDiscount + TransportPrice;

        return price;
    }

    ...

}

最好将依赖项(例如buyerStrategydiscountStrategyprice)放在构造函数中,然后通过IoC容器或其他东西填充它们,而不是在构造函数本身中创建它们。 引入_price字段后,您可以将填充价格的属性委托给Price类本身。方法Price.CalculatePrice可以作为Price类的Fabric方法调用。

答案 1 :(得分:1)

在不了解周围代码的情况下有点难以说 - 但我想也许Decorator Pattern可以解决这个问题?!因此,在您的实例中可能还有以下几点:

public abstract class BaseProduct
{
    public decimal BasePrice { get; set; }
    public decimal Addition { get; set; }
    public Transport Transport { get; set; }

    public abstract void CalculatePrice(decimal discount);
}

public class Product : BaseProduct
{
    public BasePrice Price { get; set; }

    public Product(BasePrice price)
    {
        this.Price = price;
    }

    public override void CalculatePrice(decimal discount)
    {
        this.Price.CalculatePrice(this.BasePrice, this.Addition, discount);
    }
}

public abstract class BasePrice
{
    public abstract void CalculatePrice(decimal basePrice, decimal additional, decimal discount);
}

public class Price : BasePrice
{
    public decimal ProductPrice { get; set; }
    public decimal Discount { get; set; }
    public decimal ProductPriceWithDiscount { get; set; }
    public decimal TransportPrice { get; set; }
    public decimal TotalPrice { get; set; }

    public override void CalculatePrice(decimal basePrice, decimal additional, decimal discount)
    {
        this.ProductPrice = basePrice + (basePrice * additional);
        this.Discount = this.ProductPrice * discount;
        this.ProductPriceWithDiscount = this.ProductPrice - this.Discount;
        this.TotalPrice = this.ProductPriceWithDiscount + this.TransportPrice;
    }
}

使用此方法,您可以在添加新属性时创建BasePrice的新具体实现,并且仍然支持封闭原则,因为您不需要更改原始类中的Calculate逻辑,只需在更改时添加新的具体实现。只是为了澄清 - 产品是组件,而价格是装饰器。

希望我做对了 - 对任何反馈都持开放态度!同样,希望它有所帮助! :)