Spiga

一天一个重构方法(6):提取方法对象

2009-05-14 23:03:01

Extract Method Object:提炼方法对象

当你尝试进行提炼方法的重构时,需要引入大量的方法。在一个方法中使用众多的本地变量有时会使代码变得丑陋。因此最好使用提炼方法对象这个重构,将执行任务的逻辑分开。

public class OrderLineItem
    {
        public decimal Price { get; private set; }
    }
    public class Order
    {
        private IList<OrderLineItem> OrderLineItems { get; set; }
        private IList<decimal> Discounts { get; set; }
        private decimal Tax { get; set; }
        public decimal Calculate()
        {
            decimal subTotal = 0m;
            // Total up line items
            foreach (OrderLineItem lineItem in OrderLineItems)
            {
                subTotal += lineItem.Price;
            }
            // Subtract Discounts
            foreach (decimal discount in Discounts)
                subTotal -= discount;
            // Calculate Tax
            decimal tax = subTotal * Tax;
            // Calculate GrandTotal
            decimal grandTotal = subTotal + tax;
            return grandTotal;
        }
    }

我们通过构造函数,将返回计算结果的类的引用传递给包含多个计算方法的新建对象,或者向方法对象的构造函数中单独传递各个参数。如下面的代码:

public class OrderLineItem
{
	public decimal Price { get; private set; }
}
public class Order
{
	public IEnumerable<OrderLineItem> OrderLineItems { get; private set; }
	public IEnumerable<decimal> Discounts { get; private set; }
	public decimal Tax { get; private set; }
	public decimal Calculate()
	{
		return new OrderCalculator(this).Calculate();
	}
}
public class OrderCalculator
{
	private decimal SubTotal { get; set; }
	private IEnumerable<OrderLineItem> OrderLineItems { get; set; }
	private IEnumerable<decimal> Discounts { get; set; }
	private decimal Tax { get; set; }
	public OrderCalculator(Order order)
	{
		OrderLineItems = order.OrderLineItems;
		Discounts = order.Discounts;
		Tax = order.Tax;
	}
	public decimal Calculate()
	{
		CalculateSubTotal();
		SubtractDiscounts();
		CalculateTax();
		return SubTotal;
	}
	private void CalculateSubTotal()
	{
		// Total up line items
		foreach (OrderLineItem lineItem in OrderLineItems)
			SubTotal += lineItem.Price;
	}
	private void SubtractDiscounts()
	{
		// Subtract Discounts
		foreach (decimal discount in Discounts)
			SubTotal -= discount;
	}
	private void CalculateTax()
	{
		// Calculate Tax
		SubTotal += SubTotal * Tax;
	}
}