重构之提取类
重构中的提取类是一种将单个类的职责分离到多个类中的技术。当类变得过于复杂、承担的职责过多时,可以通过提取类来将一些职责单独放到新的类中,从而提高代码的可读性、可维护性,并且使代码更加符合单一职责原则。
下面我们来具体看一下如何进行Extract Class的重构。
一、重构前的代码
假设我们有一个Customer
类,该类承担了客户信息和账单处理的职责,这就违反了单一职责原则。代码如下:
public class Customer
{
public string Name { get; set; }
public string Email { get; set; }
public List<Order> Orders { get; set; }
public Customer(string name, string email)
{
Name = name;
Email = email;
Orders = new List<Order>();
}
// 客户相关方法
public void AddOrder(Order order)
{
Orders.Add(order);
}
// 账单相关方法
public decimal GetTotalBillingAmount()
{
return Orders.Sum(order => order.Amount);
}
public void PrintBillingStatement()
{
Console.WriteLine($"Billing Statement for {Name}");
foreach (var order in Orders)
{
Console.WriteLine($"Order {order.Id}: {order.Amount:C}");
}
Console.WriteLine($"Total: {GetTotalBillingAmount():C}");
}
}
public class Order
{
public int Id { get; set; }
public decimal Amount { get; set; }
public Order(int id, decimal amount)
{
Id = id;
Amount = amount;
}
}
在这个例子中,Customer
类包含了客户信息、订单管理和账单打印等功能。账单管理的代码可以提取出来,形成一个单独的Billing
类。
二、重构后的代码
我们可以将账单相关的代码提取到一个Billing
类中。重构后的代码如下:
public class Customer
{
public string Name { get; set; }
public string Email { get; set; }
public List<Order> Orders { get; set; }
public Billing Billing { get; }
public Customer(string name, string email)
{
Name = name;
Email = email;
Orders = new List<Order>();
Billing = new Billing(this); // 将当前客户传递给Billing类
}
// 客户相关方法
public void AddOrder(Order order)
{
Orders.Add(order);
}
}
public class Billing
{
private readonly Customer _customer;
public Billing(Customer customer)
{
_customer = customer;
}
public decimal GetTotalBillingAmount()
{
return _customer.Orders.Sum(order => order.Amount);
}
public void PrintBillingStatement()
{
Console.WriteLine($"Billing Statement for {_customer.Name}");
foreach (var order in _customer.Orders)
{
Console.WriteLine($"Order {order.Id}: {order.Amount:C}");
}
Console.WriteLine($"Total: {GetTotalBillingAmount():C}");
}
}
public class Order
{
public int Id { get; set; }
public decimal Amount { get; set; }
public Order(int id, decimal amount)
{
Id = id;
Amount = amount;
}
}
三、分析重构后的代码
- 将账单逻辑提取到Billing类:现在账单计算和打印的逻辑位于
Billing
类中,而不再属于Customer
类。Billing
类专注于与账单相关的操作,符合单一职责原则。 - 简化Customer类:现在
Customer
类的职责仅限于客户信息和订单的管理,不再负责账单处理的逻辑。 - 提高可维护性:随着应用的扩展,
Billing
类可以独立修改和扩展,而不会影响Customer
类。
通过这种重构方式,我们将复杂的职责分离,使代码更具可读性和扩展性。