重构指南 - 封装集合(Encapsulate Collection)
封装就是将相关的方法或者属性抽象成为一个对象。
封装的意义:
- 对外隐藏内部实现,接口不变,内部实现自由修改。
- 只返回需要的数据和方法。
- 提供一种方式防止数据被修改。
- 更好的代码复用。
当一个类的属性类型为集合,或者方法返回类型为集合时,如果符合以下条件,我们就可以考虑将集合进行封装:
- 返回的数据仅用于展示
- 当集合的Add,Remove方法包含其它业务逻辑
向类的调用者隐藏类中的完整集合有如下几个好处:
- 保证返回的集合数据不会被修改。
- 在Add, Remove方法中可以添加验证,日志或其他业务逻辑。
代码示例:
using System.Collections.Generic; namespace LosTechies.DaysOfRefactoring.EncapsulateCollection.Before { public class Order { private List<OrderLine> _orderLines; private double _orderTotal; public IList<OrderLine> OrderLines { get { return _orderLines; } } public void AddOrderLine(OrderLine orderLine) { _orderTotal += orderLine.Total; _orderLines.Add(orderLine); } public void RemoveOrderLine(OrderLine orderLine) { orderLine = _orderLines.Find(o => o == orderLine); if (orderLine == null) return; _orderTotal -= orderLine.Total; _orderLines.Remove(orderLine); } } public class OrderLine { public double Total { get; private set; } } }
上面的代码在Add或者Remove orderLine时存在业务逻辑,如果调用时直接修改OrderLines的元素,就会产生bug,所以需要重构如下:
using System.Collections.Generic; namespace LosTechies.DaysOfRefactoring.EncapsulateCollection.After { public class Order { private List<OrderLine> _orderLines; private double _orderTotal; //方法一:返回IEnumerable类型 public IEnumerable<OrderLine> OrderLines { get { return _orderLines.Skip(0); } } //方法二:返回只读类型 public ReadOnlyCollection<OrderLine> OrderLines { get { return _orderLines.AsReadOnly(); } } public void AddOrderLine(OrderLine orderLine) { _orderTotal += orderLine.Total; _orderLines.Add(orderLine); } public void RemoveOrderLine(OrderLine orderLine) { orderLine = _orderLines.Find(o => o == orderLine); if (orderLine == null) return; _orderTotal -= orderLine.Total; _orderLines.Remove(orderLine); } } public class OrderLine { public double Total { get; private set; } } }
注意:虽然直接返回IEnumerable,这样只能遍历取出它的值,但是还是可以通过转换为List后操作集合中的元素,所以我们采用_orderLines.Skip(0)迭代返回,这样就能阻止调用者转换为list。
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步