最近写了一个排序的程序
需求从最开始的只要能对数组进行升序排序不断的进化
最后成为以下的样子:
1 可以升序和降序排序
2 能够自由的扩充排序算法而不需改动原有程序
3 能纪录排序的比较次数、交换次数、排序用时
4 通过扩展,能够对任意对象进行排序
5 通过扩展,能够将排序过程相关的信息打印在任何位置
所以代码从最开始的一个简单的函数被重构成了
包含3个 接口、N个类的包
程序的输出入下:
**********************************************
2005-10-12 0:16:57
The original array is :
2005-01-01 6:06:06,2004-01-01 6:06:06,2006-01-01 6:06:06,2005-01-01 6:06:07
Now using BubbleSorter, direction : Descending
Sort was finished.
Sort took 40.0576 ms.
Sort compared 6 times.
Sort swapped 4 times.
The sorted array is :
2006-01-01 6:06:06,2005-01-01 6:06:07,2005-01-01 6:06:06,2004-01-01 6:06:06
**********************************************
2005-10-12 0:16:57
The original array is :
1,3,2,4,5,6.5,7,8
Now using BubbleSorter, direction : Ascending
Sort was finished.
Sort took 20.0288 ms.
Sort compared 13 times.
Sort swapped 1 times.
The sorted array is :
1,2,3,4,5,6.5,7,8
………………(其余部分省略)
起初,BubbleSorter的代码如下

/**//// <summary>
/// 冒泡排序算法,使用了策略模式避免了对具体比较器的依赖
/// </summary>
public class BubbleSorter : SorterBase

{

/**//// <summary>
/// 构造器
/// </summary>
public BubbleSorter():this(new CommonComparer(),new ConsolePrinter())

{
}


/**//// <summary>
/// 构造器
/// </summary>
/// <param name="comparer">比较器实例</param>
public BubbleSorter(IComparer comparer):this(comparer,new ConsolePrinter())

{
}


/**//// <summary>
/// 构造器
/// </summary>
/// <param name="comparer">比较器实例</param>
/// <param name="printer">打印器实例</param>
public BubbleSorter(IComparer comparer,IPrinter printer)

{
Initialize(comparer,printer);
}


public override void Sort(Array arrayToSort,SortDirection sortDirection)

{
if(arrayToSort == null) throw new ArgumentNullException("arrayToSort");

StartSort(this,arrayToSort,sortDirection);
bool isSwap = false ;

try

{
for(int i = 0 ; i <= arrayToSort.Length - 1 ; i ++)

{
isSwap = false ;
for(int j = arrayToSort.Length-2 ; j >= i ; j --)

{
if(CompareAndSwap(arrayToSort,j,j+1))
isSwap = true;
}
if(!isSwap) break ;
}

FinishSort(arrayToSort);
}
catch(Exception ex)

{
RegisterException(ex);
throw;
}
}
}
当只有冒泡排序算法的时候,我对上面的程序感觉相当满意。
但是,在我实现插入排序的话,我发现了几个很不爽的事情
1。基本我要实现跟冒泡排序一样的3个构造方法
2。对于Sort方法 我必须作参数校验
3。为了显示排序信息,我必须在排序过程前后调用StartSort(this,arrayToSort,sortDirection)和FinishSort(arrayToSort)方法
4。在BubbleSorter类中和SortBase类中,很多方法都在传递arrayToSort这个参数
于是我做了几件事
1。用Extra Method将真正排序的那段代码提取到一个叫做DoSort()的方法中
2。将Sort方法提取到Super Class中,在Sort中调用抽象的 DoSort方法。--- 这刚好是模板模式。
3。将arrayToSort提升为域字段
4。去除了3个烦躁的构造函数,转而使用工厂进行构造
经过3步重构后,排序的算法保持得很纯洁,如下:

/**//// <summary>
/// 冒泡排序算法
/// </summary>
public class BubbleSorter : SorterBase

{
protected override void DoSort()

{
bool isSwap = false ;
for(int i = 0 ; i <= arrayToSort.Length - 1 ; i ++)

{
isSwap = false ;
for(int j = arrayToSort.Length-2 ; j >= i ; j --)

{
if(CompareAndSwap(j,j+1))
isSwap = true;
}
if(!isSwap) break ;
}
}
}
插入排序的代码

/**//// <summary>
/// 直接插入排序
/// </summary>
public class InsertSorter : SorterBase

{

/**//// <url>element://model:project::Sorter/design:view:::zm86v8buarhrn1i_v</url>
/// <url>element://model:project::Sorter/design:view:::kg8jy20srni144i_v</url>
protected override void DoSort()

{
for(int i=1;i< arrayToSort.Length;i++)

{
//依次与前面的记录进行比较,如比它小就交换
for(int j=i;j>0;j--)

{
if( !CompareAndSwap( j-1 , j) ) break;
}
}
}
}
编码采用了TDD,如果没有单元测试,重构会是一场噩梦。
对于用于测试的代码也经过了重构
最开始只有一个类用于测试冒泡排序代码
后来加入了插入排序算法以后
发现原先的测试代码没有办法重用,于是抽象出了一个测试基类TestSorterBase,这个类里面存在大量的测试方法,但是这个类没有被标记[TestFixture]
从里面派生出的两个类 TestInsertSorter & TestBubbleSorter,被标记为[TestFixture],却没有声明任何[Test]特性的方法
代码如下

/**//// <summary>
/// TestInsertSort 的摘要说明。
/// </summary>
[TestFixture]
public class TestBubbleSorter : TestSortBase

{
protected override SorterBase CreateSorter()

{
return SorterFactory.GetSorter( typeof( BubbleSorter ) );
}
} 这个稍候再作详细的介绍。
呵呵 偶还在增加需求 继续重构
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 分享 3 个 .NET 开源的文件压缩处理库,助力快速实现文件压缩解压功能!
· Ollama——大语言模型本地部署的极速利器
· [AI/GPT/综述] AI Agent的设计模式综述