第三章 体验重构
个人强烈推荐《重构--改善既有代码的设计》(不过建议有2年以上的开发人员看,太早看是浪费时间)。
本章,作者用来一个阶乘容器的设计来说明重构。
3.1 一个阶乘容器
通常,作为一个初学者,我们的代码最初会设计如下:
![ContractedBlock.gif](https://www.cnblogs.com/Images/OutliningIndicators/ContractedBlock.gif)
![ExpandedBlockStart.gif](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedBlockStart.gif)
class FactorialContainer
{
public FactorialContainer()
{
m_factorialList = new ArrayList();
}
public FactorialContainer(int capacity)
{
m_capacity = capacity;
m_factorialList = new ArrayList(capacity);
}
protected ArrayList m_factorialList;
protected int m_capacity;
public int Capacity
{
get { return m_capacity; }
set { m_capacity = value; }
}
public long this[int index]
{
get { return (long)m_factorialList[index]; }
set { m_factorialList[index] = value; }
}
public void Add()
{
long result = 1;
int seed = m_factorialList.Count + 1;
for (int i = 1; i <= seed; i++)
{
result *= i;
}
m_factorialList.Add(result);
}
public void RemoveAt(int index)
{
m_factorialList.RemoveAt(index);
}
public void Clear()
{
m_factorialList.Clear();
}
}
3.2 代码的坏味道
上面的代码计算阶乘的算法与元素的添加行为紧密的纠缠在一起。根据职责分离原则,需要进行分离。
![ContractedBlock.gif](https://www.cnblogs.com/Images/OutliningIndicators/ContractedBlock.gif)
![ExpandedBlockStart.gif](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedBlockStart.gif)
public void Add()
{
long result = CountFactorial();
m_factorialList.Add(result);
}
private long CountFactorial()
{
long result = 1;
int seed = m_factorialList.Count + 1;
for (int i = 1; i <= seed; i++)
{
result *= i;
}
return result;
}
3.3 需求发生变化
后来我们的需求发生变化,需要增加菲波那契数列的计算。
经过重构:
![ContractedBlock.gif](https://www.cnblogs.com/Images/OutliningIndicators/ContractedBlock.gif)
![ExpandedBlockStart.gif](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedBlockStart.gif)
public abstract class MathContainer
{
public MathContainer()
{
m_mathList = new ArrayList();
}
public MathContainer(int capacity)
{
m_capacity = capacity;
m_mathList = new ArrayList(capacity);
}
protected ArrayList m_mathList;
protected int m_capacity;
public int Capacity
{
get { return m_capacity; }
set { m_capacity = value; }
}
public long this[int index]
{
get { return (long)m_mathList[index]; }
set { m_mathList[index] = value; }
}
public void Add()
{
m_mathList.Add(Count());
}
public void RemoveAt(int index)
{
m_mathList.RemoveAt(index);
}
public void Clear()
{
m_mathList.Clear();
}
protected abstract long Count();
}
![ContractedBlock.gif](https://www.cnblogs.com/Images/OutliningIndicators/ContractedBlock.gif)
![ExpandedBlockStart.gif](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedBlockStart.gif)
public class FactorialContainer : MathContainer
{
public FactorialContainer() : base() { }
public FactorialContainer(int capacity) : base(capacity) { }
protected override long Count()
{
long result = 1;
int seed = m_factorialList.Count + 1;
for (int i = 1; i <= seed; i++)
{
result *= i;
}
return result;
}
}
public class FibonacciContainer : MathContainer
{
public FibonacciContainer() : base() { }
public FibonacciContainer(int capacity) : base(capacity) { }
protected override long Count()
{
long result = 0;
int seed = m_mathList.Count;
if (seed == 0 || seed == 1)
{
result = 1;
}
else
{
result = this[seed - 1] + this[seed - 2];
}
return result;
}
}
呵呵,上面是Template Method 模式。
3.5引入设计模式
使用工厂模式来管理实例的创建。
![ContractedBlock.gif](https://www.cnblogs.com/Images/OutliningIndicators/ContractedBlock.gif)
![ExpandedBlockStart.gif](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedBlockStart.gif)
public abstract class MathFactory
{
public abstract MathContainer CreateInstance();
public abstract MathContainer CreateInstance(int capacity);
}
public class FactorialFactory : MathFactory
{
public override MathContainer CreateInstance()
{
return new FactorialContainer();
}
public override MathContainer CreateInstance(int capacity)
{
return new FactorialContainer(capacity);
}
}
public class FibonacciFactory : MathFactory
{
public override MathContainer CreateInstance()
{
return new FibonacciContainer();
}
public override MathContainer CreateInstance(int capacity)
{
return new FibonacciContainer(capacity);
}
}
通过工厂对象,通过它来创建需要的具体容器类对象了。
![ContractedBlock.gif](https://www.cnblogs.com/Images/OutliningIndicators/ContractedBlock.gif)
![ExpandedBlockStart.gif](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedBlockStart.gif)
[STAThread]
static void Main(string[] args)
{
MathFactory factory1 = new FactorialFactory();
MathFactory factory2 = new FibonacciFactory();
MathContainer factorial = factory1.CreateInstance();
MathContainer fibonacci = factory2.CreateInstance();
Console.WriteLine("Count Factorial form 1 to 8:");
for (int i = 1; i <= 8; i++)
{
factorial.Add();
}
for (int i = 0; i < 8; i++)
{
Console.WriteLine(factorial[i].ToString());
}
Console.WriteLine();
Console.WriteLine("Count Fibonacci form 1 to 8:");
for (int i = 1; i <= 8; i++)
{
fibonacci.Add();
}
for (int i = 0; i < 8; i++)
{
Console.WriteLine(fibonacci[i].ToString());
}
Console.ReadLine();
}