封装就是将相关的方法或者属性抽象成为一个对象。

封装的意义:

  1. 对外隐藏内部实现,接口不变,内部实现自由修改。
  2. 只返回需要的数据和方法。
  3. 提供一种方式防止数据被修改。
  4. 更好的代码复用。
当一个类的属性类型为集合,或者方法返回类型为集合时,如果符合以下条件,我们就可以考虑将集合进行封装:
  1. 返回的数据仅用于展示
  2. 当集合的Add,Remove方法包含其它业务逻辑
向类的调用者隐藏类中的完整集合有如下几个好处:
  1. 保证返回的集合数据不会被修改。
  2. 在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(); }
} //方法二:返回只读类型
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。

最新文章

  1. pygame系列_原创百度随心听音乐播放器_完整版
  2. MD5签名方法
  3. cf div2 239 D
  4. angularJS $resource与后台restapi的对应关系
  5. hdu 3715
  6. SPI,UART,I2C都有什么区别,及其各自的特点
  7. 【转】stdin, stdout, stderr 以及重定向
  8. ping时不知道ping那个Ip的解决办法
  9. Java集合(5)一 HashMap与HashSet
  10. Collection集合框架详解
  11. JSoup抓取本地页面
  12. 30 个java编程技巧
  13. Mysql在master上查看有哪些slave
  14. python处理excel之读:xlrd模块
  15. javascript基础拾遗(二)
  16. &lt;邱永汉股票入门&gt;读书笔记
  17. width:100%和width:auto区别
  18. c++ 指针访问数组
  19. 阿里云maven仓库镜像mirror,速度超快
  20. CentOS按电源键关机

热门文章

  1. 03.SQLServer性能优化之---存储优化系列
  2. wepack+sass+vue 入门教程(二)
  3. CMS模板应用调研问卷
  4. 这些.NET开源项目你知道吗?.NET平台开源文档与报表处理组件集合(三)
  5. NET Core-学习笔记(三)
  6. Spark踩坑记——初试
  7. 解决VS2008在win7找不到输入序列号的地方
  8. IT雇员及外包商选择:人品第一
  9. SSH免手动输入密码和设置代理
  10. DockerCon 2016 – 微软带来了什么?