理解:封装集合就是把集合进行封装,只提供调用者所需要的功能行借口,保证集合的安全性。
详解:在大多的时候,我们没有必要把所有的操作暴露给调用者,只需要把调用者需要的相关操作暴露给他,这种情况中下我们就要对其进行封装,只把调用者需要的部分暴露出来。
我们先看一个例子:
1 using System; 2 using System.Collections.Generic; 3 using System.Linq; 4 using System.Text; 5 6 namespace _31DaysOfReflactor 7 { 8 public class Order 9 { 10 private List<OrderLine> _orderLines; 11 private double _orderTotal; 12 13 public IList<OrderLine> OrderLines 14 { 15 get { return _orderLines; } 16 } 17 18 public void AddOrderLine(OrderLine orderLine) 19 { 20 _orderTotal += orderLine.Total; 21 _orderLines.Add(orderLine); 22 } 23 24 public void RemoveOrderLine(OrderLine orderLine) 25 { 26 orderLine = _orderLines.Find(o => o == orderLine); 27 28 if (orderLine == null) 29 return; 30 31 _orderTotal -= orderLine.Total; 32 _orderLines.Remove(orderLine); 33 } 34 } 35 36 public class OrderLine 37 { 38 public double Total { get; private set; } 39 } 40 }
如果我们对集合只允许调用端读取,遍历取值,而不允许其修改集合的值,那么我们把IList换成了IEnumerable。IEnumerable只包括一个返回值为IEnumerator的GetEnumerator()方法,用来遍历取值,就达到我们想要的目的。
重构后的代码如下:
1 using System; 2 using System.Collections.Generic; 3 using System.Linq; 4 using System.Text; 5 6 namespace _31DaysOfReflactor 7 { 8 public class Order 9 { 10 private List<OrderLine> _orderLines; 11 private double _orderTotal; 12 13 public IEnumerable<OrderLine> OrderLines 14 { 15 get { return _orderLines; } 16 } 17 18 public void AddOrderLine(OrderLine orderLine) 19 { 20 _orderTotal += orderLine.Total; 21 _orderLines.Add(orderLine); 22 } 23 24 public void RemoveOrderLine(OrderLine orderLine) 25 { 26 orderLine = _orderLines.Find(o => o == orderLine); 27 28 if (orderLine == null) 29 return; 30 31 _orderTotal -= orderLine.Total; 32 _orderLines.Remove(orderLine); 33 } 34 } 35 36 public class OrderLine 37 { 38 public double Total { get; private set; } 39 } 40 }
如上所示,我们对IList集合进行封装,没有把该集合的add/remove方法暴露给调用端。当然在.Net framework中提供了很多封装好的集合类,不同的类都有不同的作用,比如ReadOnlyCollection 集合,但是他们每个集合都有自己的使用局限性。上面的重构是一个值得注意的非常简单的例子,像这样的封装能够确保客户端不会错误的调用集合以免引进bugs。