关于.NET Framework中的设计模式

编程时遇到排序在平常不过,使用.Net最常见的就是对泛型List<T>进行排序,如果T是简单数据类型排序那么很简单

复制代码 代码如下:


public List<int> SortSimpleList(List<int> list)
{
list.Sort();
return list;
}

同样对string等简单类型List<T>排序均如此,如果我们要排的对象复杂了怎么办,我们知道List<T> sort()最后是用快速排序实现,快速排序也好,什么排序都需要知道list中item之间的比较结果,如果是简单的int类型,直接判断即可,对实现了IComparable接口的对象,可以调用其CompareTo()实现item比较大小,下面是一个快速排序的写法

复制代码 代码如下:


void Sort<T>(T[] array, int left, int right, IComparer_sly<T> comparer) where T : IComparable
{
if (left < right)
{
T middle = array[(left + right) / 2];
int i = left - 1;
int j = right + 1;
while (true)
{
while (array[++i].CompareTo(middle) < 0) ;

while (array[--j].CompareTo(middle) > 0) ;

if (i >= j)
break;

T temp = array[i];
array[i] = array[j];
array[j] = temp;
}

Sort(array, left, i - 1, comparer);
Sort(array, j + 1, right, comparer);
}
}

问题

对于前两种情况固然可以实现排序,但是我们不可能要求所有待排序的对象都实现IComparable接口,就算能够保证每个对象都实现IComparable接口,如果想实现对象内多个字段排序,比如Student对象,有时候想按照姓名排序,有时候是成绩,有时候是年龄,这怎么破

按照面向对象的思想,要把变化独立出来,封装变化,对于我们排序List<T>时变化的其实就是怎么比较两个对象的大小的算法,如果我们可以把这个算法拿出来,排序就简单了很多,无论什么排序,算法都是由的,我们要封装的部分是怎样比较两个item的大小的算法,为了实现拓展性我们要遵循面向对象设计的另外一个重要原则,针对接口编程,而不是针对实现编程。

编写通用的List<T>排序方法

首先定义一个接口,里面有一个比较item大小的方法,在排序的时候作为参数传入,当然是传入它的实现类,有了这个想法,我们可以自己写个List<T>的排序方法

复制代码 代码如下:


public interface mparer_sly<T>{
int Compare(T x, T y);
}

然后为了测试,我们为List<T>加一个包装,写一个自己的Sort方法,内部也用快速排序实现。一直困惑我们的变化部分——比较大小算法,我们把它封转起来,作为参数传入

复制代码 代码如下:


using System;
using System.Collections.Generic;

namespace Test.Stategy
{public class ListTest<T>
{
public List<T> list = new List<T>();
public void Sort(IComparer_sly<T> comparer)
{
T[] array = list.ToArray();
int left = 0;
int right = array.Length - 1;
QuickSort(array, left, right, comparer);
list = new List<T>(array);
}

private void QuickSort<S>(S[] array, int left, int right, IComparer_sly<S> comparer)
{
if (left < right)
{
S middle = array[(left + right) / 2];
int i = left - 1;
int j = right + 1;
while (true)
{
while (comparer.Compare(array[++i], middle) < 0) ;

while (comparer.Compare(array[--j], middle) > 0) ;

if (i >= j)
break;

S temp = array[i];
array[i] = array[j];
array[j] = temp;
}

QuickSort(array, left, i - 1, comparer);
QuickSort(array, j + 1, right, comparer);
}
}
}
}

比如现在我们有个Student 的实体

复制代码 代码如下:


public class Student
{
public Student(int id, string name)
{
this.ID = id;
this.Name = name;
}
public int ID { get; set; }
public string Name { get; set; }
}

如果想对这个实体组成的List<T>进行排序,我们只需一个实现 IComparer_sly<Student>的类 StudentComparer,并在内部实现其比较大小方法——Compare(),同时我们可以添加递增还是递减排序的控制

复制代码 代码如下:


class StudentComparer : IComparer_sly<Student>
{
private string expression;
private bool isAscending;
public StudentComparer(string expression, bool isAscending)
{
this.expression = expression;
this.isAscending = isAscending;
}

public int Compare(Student x, Student y)
{
object v1 = GetValue(x), v2 = GetValue(y);
if (v1 is string || v2 is string)
{
string s1 = ((v1 == null) ? "" : v1.ToString().Trim());
string s2 = ((v2 == null) ? "" : v2.ToString().Trim());
if (s1.Length == 0 && s2.Length == 0)
return 0;
else if (s2.Length == 0)
return -1;
else if (s1.Length == 0)
return 1;
}

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/wjgsps.html