重构第1天:封装集合(Encapsulate Collection)

理解:封装集合就是把集合进行封装,只提供调用者所需要的功能行借口,保证集合的安全性。

详解:在大多的时候,我们没有必要把所有的操作暴露给调用者,只需要把调用者需要的相关操作暴露给他,这种情况中下我们就要对其进行封装,只把调用者需要的部分暴露出来。

我们先看一个例子:

 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。

原文地址:https://www.cnblogs.com/yplong/p/5276598.html