设计模式-策略模式

1.开始我们想要这样一个类Sorter, 通过里面的Sort方法可以将一个int数组排序,这里我们用选择排序来实现

1 int[] arr = { 9, 2, 3, 5, 7, 1, 4 };
2 
3             Sorter sorter = new Sorter();
4 
5             sorter.Sort(arr);
 1 public class Sorter
 2     {
 3         public void Sort(int[] arr) 
 4         {
 5             for (int i = 0; i < arr.Length - 1; i++)
 6             {
 7                 int curr_pos = i;
 8 
 9                 for (int j = i + 1; j < arr.Length; j++)
10                 {
11                     if (arr[curr_pos] > arr[j])
12                     {
13                         //交换下标
14                         curr_pos = j;
15 
16                     }
17                 }
18 
19                 //交换位置
20                 ExchangeLocation(arr, curr_pos, i);
21             }
22         }
23 
24         public static void ExchangeLocation(int[] arr, int a, int b)
25         {
26             int temp = arr[a];
27             arr[a] = arr[b];
28             arr[b] = temp;
29         }
30 
31 
32     }

2.接下来就要对方法扩展,如果我们想要对double 数组排序,想要对float数组排序呢?难道是再写两个方法吗?如果是对Cat类来排序呢?来看下面的Cat类

如果要比较Cat的大小必须提供一个比较方法

 

 1 public class Cat
 2     {
 3         public int Weight { get; set; }
 4 
 5         public int Height { get; set; }
 6 
 7         public Cat(int weight,int height)
 8         {
 9             this.Weight = weight;
10             this.Height = height;
11         }
12 
13         public int CompareTo(Cat c)
14         {
15             if (this.Weight < c.Weight)
16                 return -1;
17             else if (this.Weight > c.Weight)
18                 return 1;
19             else
20                 return 0;
21         }
22     }

 

 

 

3.然后在Sorter里面添加排序猫的方法

 

 1 public void SortCat(Cat[] arr)
 2         {
 3             for (int i = 0; i < arr.Length - 1; i++)
 4             {
 5                 int curr_pos = i;
 6 
 7                 for (int j = i + 1; j < arr.Length; j++)
 8                 {
 9                     if (arr[curr_pos].CompareTo(arr[j])==1)
10                     {
11                         //交换下标
12                         curr_pos = j;
13 
14                     }
15                 }
16 
17                 //交换位置
18                 ExchangeLocationCat(arr, curr_pos, i);
19             }
20         }
21 
22         public static void ExchangeLocationCat(Cat[] arr, int a,int b)
23         {
24             Cat temp = arr[a];
25             arr[a] = arr[b];
26             arr[b] = temp;
27         }

 4.那么如果要对狗,对车,对运动员进行排序呢?在上述Sorter 类中我们都写成固定的SortCat ,SortIntArray等等方法,没有一个通用的方法来实现排序,那么怎么能够抽象出一个通用的方法呢?

很容易想到的方法是将Sort方法的参数改成实现接口Comparable的数组,Comparable接口的有一个CompareTo方法,所有想要排序的数组的元素类型

必须要实现Comparable,也就是说狗,车,运动员如果想要排序,就必须实现Comparable接口,传入对应的排序规则CompareTo   代码改写如下:

 

1  public interface Comparable
2     {
3         int CompareTo(object o);
4     }

 

 1 public void SortComparable(Comparable[] arr)
 2         {
 3             for (int i = 0; i < arr.Length - 1; i++)
 4             {
 5                 int curr_pos = i;
 6 
 7                 for (int j = i + 1; j < arr.Length; j++)
 8                 {
 9                     if (arr[curr_pos].CompareTo(arr[j])==1)
10                     {
11                         //交换下标
12                         curr_pos = j;
13 
14                     }
15                 }
16 
17                 //交换位置
18                 ExchangeLocationComparable(arr, curr_pos, i);
19             }
20         }
21 
22         public static void ExchangeLocationComparable(Comparable[] arr, int a,int b)
23         {
24             Comparable temp = arr[a];
25             arr[a] = arr[b];
26             arr[b] = temp;
27         }
 1 public class Cat: Comparable
 2     {
 3         public int Weight { get; set; }
 4 
 5         public int Height { get; set; }
 6 
 7         public Cat(int weight,int height)
 8         {
 9             this.Weight = weight;
10             this.Height = height;
11         }
12 
13         //public override int CompareTo(Cat c)
14         //{
15         //    if (this.Weight < c.Weight)
16         //        return -1;
17         //    else if (this.Weight > c.Weight)
18         //        return 1;
19         //    else
20         //        return 0;
21         //}
22 
23         public override string ToString()
24         {
25             return $"catHeight:{this.Height},weight:{this.Weight}";
26         }
27 
28         public int CompareTo(object o)
29         {
30             Cat c = (Cat)o;
31             if (this.Weight < c.Weight)
32                 return -1;
33             else if (this.Weight > c.Weight)
34                 return 1;
35             else
36                 return 0;
37         }
38     }

5.故事进行到这里看起来一切都很美好, 如果想要对一个类排序,那么就去实现Comparable 接口好了。但是事实却没有这么简单, 现在的需求变了:我们想在对猫进行排序的时候,不光想按

照体重对它排序,我们还想按照身高进行排序 ,如果以后对猫扩展其他属性的话,有可能会按照其他属性排序,那么该怎么办? 我的想法是传入规则,就是传入一个判断的方法,参数是一个方法,

排序的时候你想按照什么规则排序,你就传入那个规则的方法,我们可以定义一个比较器,参数同样是要比较的类和按照什么规则比较的方法:

1    public interface Comparator<T>
2     {
3         int Compare(T o1, T o2);
4     }
 1 public class Cat
 2     {
 3         public int Weight { get; set; }
 4 
 5         public int Height { get; set; }
 6 
 7         public Cat(int weight,int height)
 8         {
 9             this.Weight = weight;
10             this.Height = height;
11         }
12 
13         public override string ToString()
14         {
15             return $"catHeight:{this.Height},weight:{this.Weight}";
16         }
17 
18     }
 1 public class Sorter<T>
 2     {
 3 
 4         public void Sort(T[] arr, Comparator<T> comparator)
 5         {
 6             for (int i = 0; i < arr.Length - 1; i++)
 7             {
 8                 int curr_pos = i;
 9 
10                 for (int j = i + 1; j < arr.Length; j++)
11                 {
12                     if (comparator.Compare(arr[curr_pos],arr[j])==1)
13                     {
14                         //交换下标
15                         curr_pos = j;
16 
17                     }
18                 }
19 
20                 //交换位置
21                 ExchangeLocationComparable(arr, curr_pos, i);
22             }
23         }
24 
25         public static void ExchangeLocationComparable(T[] arr, int a,int b)
26         {
27             T temp = arr[a];
28             arr[a] = arr[b];
29             arr[b] = temp;
30         }
31 
32     }
 1 public class CatHeightComparator : Comparator<Cat>
 2     {
 3         public int Compare(Cat o1, Cat o2)
 4         {
 5             if (o1.Height<o2.Height)
 6             {
 7                 return -1;
 8             }
 9             else if (o1.Height == o2.Height)
10             {
11                 return 0;
12             }
13             else 
14             {
15                 return 1;
16             }
17         }
18     }

 

调用

1   Cat[] arr = new Cat[] { new Cat(3, 3), new Cat(5, 5), new Cat(1, 1) };
2             Sorter<Cat> sorter = new Sorter<Cat>();
3             sorter.Sort(arr,new CatHeightComparator());
4 
5             PrintCat(arr);
6 
7             Console.ReadKey();

6.这样一来可以看到,猫用不着实现Comparable了, 我们想按照猫的身高排序,只需写一个CatHeightComparator比较器,对体重排序就写一个CatWeightComparator,比较的规则

形成一个方法并当做参数传入,增加了Sort方法的灵活性,而且这种设计非常符合开闭原则

 

7.总结:策略模式的关键词是策略,在这片文章中我定义它为规则, 什么情况下需要使用策略模式呢? 比如我们计算员工月工资,计算会员的月积分,都需要有一个计算公式,每一个员工

都有可能又不一样的计算规则,每一个会员根据等级也可能会有不同的计算方式,在多数简单的场景下,我们习惯使用if else 或者switch 等等分支语句,但是当规则复杂到一定程度时

而且有可能发生频繁变化时,我们应该尝试使用一些策略模式的思想来完成

注意我上面的发生频繁变化,如果业务基本不会发生变化时,我们使用设计模式时就要做出权衡,但是话又说回来,我们怎么知道这块业务不会发生变化呢?所以我们应该在写代码的时候就

需要判断哪里有可能发生变化,使用一些设计模式,在代码需要重构的时候,我们也应该想到使用设计模式来帮助我们解决相关问题

 

posted on 2020-10-31 22:53  雯烈  阅读(111)  评论(0编辑  收藏  举报