《软件设计精要与模式》读书笔记(三)
第三章 体验重构
个人强烈推荐《重构--改善既有代码的设计》(不过建议有2年以上的开发人员看,太早看是浪费时间)。
本章,作者用来一个阶乘容器的设计来说明重构。
3.1 一个阶乘容器
通常,作为一个初学者,我们的代码最初会设计如下:
Code
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();
}
}
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 代码的坏味道
上面的代码计算阶乘的算法与元素的添加行为紧密的纠缠在一起。根据职责分离原则,需要进行分离。
Code
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;
}
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 需求发生变化
后来我们的需求发生变化,需要增加菲波那契数列的计算。
经过重构:
Code
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();
}
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();
}
Code
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;
}
}
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引入设计模式
使用工厂模式来管理实例的创建。
Code
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);
}
}
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);
}
}
通过工厂对象,通过它来创建需要的具体容器类对象了。
Code
[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();
}
[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();
}
作者:心不蒙尘
出处:http://www.cnblogs.com/stan0714/
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。
该文章也同时发布在我的独立博客中-心不蒙尘。