首页 > 代码库 > 一 策略模式

一 策略模式

策略模式

    策略模式定义一系列的算法,并将每个算法进行封装,而且使他们可以相互替换,是算法与客户端(调用者)隔离开来,可以独立变化。

应用场景

    多个类只是表现行为不同,在运行时根据需要动态选择执行的算法
    客户端需要在不同情况下调用不同的算法,或者在将来算法可能会被改变
    算法对于客户端隐藏全部实现,彼此之间相互独立

策略模式的简单应用

    数学老师找到程序员小明说,给你一个长方形,写一个程序给我算一下它的周长吧,小明想“妈蛋,那么简单还来找我,不知道你物理怎么老师怎么教你的”
public class RecTangle 
    {
      public double Width { private set; get; } 
      public double Heiht { private set; get; } 
      public RecTangle(double width, double height)
      {
          Width = width;
          Heiht = height;
      }
    }
    小明不假思索写出了下面的代码,并交给了数学老师
public class Caculator 
    { 
        public static double Perimeter(RecTangle r)
        { 
            return 2 * (r.Width + r.Heiht);
        }
    }
    过了几天数学老师又来找小明说,再给我写个程序求一下它的面积吧,小明想“靠不能老这样被牵着鼻子走吧,过两天再让我求长宽比了咋不能”,看似简单的问题原来不简单。
    经过考虑小明想既然算法可能改变,那就把可能改变的抽象出来吧,恩,对就用策略模式吧
//抽象策略,定义策略接口 
public interface ICaculator
    { 
        double Caculate(RecTangle r);
    }
 
//求周长算法 
public class Perimeter:ICaculator
    { 
        public double Caculate(RecTangle r)
        { 
            return 2 * (r.Width + r.Heiht);
        }
    }
 
//求面积算法 
public class Area: ICaculator
    { 
        public double Caculate(RecTangle r)
        { 
            return r.Width * r.Heiht;
        }
    }
 
//提供策略的包装类 
public class Context 
    { 
        private ICaculator caculator; 
        public Context(ICaculator caculator)
        { 
            this.caculator = caculator;
        } 
        public double Operate(RecTangle r)
        { 
            return this.caculator.Caculate(r);
        }
    }
调用方只需根据需要调用不同的策略即可
Context context1 = new Context(new Perimeter()); 
RecTangle r = new RecTangle(10, 13); 
double d1 = context1.Operate(r); 
//求周长
Console.WriteLine("周长为:{0}", d1); 
//求面积
Context context2 = new Context(new Area()); 
double d2 = context2.Operate(r); 
Console.WriteLine("面积为:{0}", d2);
后续如需要对算法做扩展只需要新建一个类并实现ICaculator即可,扩展较为方便。

策略模式在.NET中的应用

System.Collections.ArrayList下的Sort(IComparer)方法即可理解为策略模式的一种,我们可以根据需要自定义策略(算法)然后供Sort方法使用
定义策略
        publicclass MyStrategy : IComparer<string>
        { 
public int Compare(string x, string y)
          {
               return x.CompareTo(y);
          }
        }
 
客户端调用策略
List<string> list = new List<string>();
list.Add("The");
list.Add("Abd");
list.Add("Uhn");
list.Add("Oin");
list.Add("Nmj");
list.Add("Onk");
list.Add("Lnh");
list.Add("Fhh");
list.Sort(new MyStrategy()); 
foreach (var str in list)
{ 
    Console.WriteLine(str);
}
输出
 
 

策略模式的优缺点

    优点:
    比继承更加灵活,算法彼此独立,扩展性强
    避免系统使用多重条件选择,是系统更加简洁易于扩展
    缺点:
    客户端必须知道所有的策略并且能够分辨出不同情况下调用何种策略。
    策略模式会带来很多策略类,维护相对工作量多