引用 大话设计模式(最近刚开始看这本书,写的很不错,挺吸引人的,所以记录下来,防止忘记.如有侵权,请联系我)
Strategy策略模式是属于设计模式中对象行为型模式,主要是定义一系列的算法,把这些算法一个个封装成单独的类.
UML图
看了上图,我们可以知道,在策略模式中,我们定义一系列的算法,将这些算法风装成单独的类,客户通过一个中间环境变量来调用不同的算法。还是不知道怎么表述 哈哈。。 代码说话
现在有一个商场有各种各样的优惠活动,打折、买300返100等等。
我们先构建一个优惠活动类
- public abstract class CashSuper
- {
- public abstract double acceptCash(double money);
- }
然后有各种各样优惠的活动 继承此类
- public class CashNormal:CashSuper //正常收费
- {
- public override double acceptCash(double money)
- {
- return money;
- //throw new Exception("The method or operation is not implemented.");
- }
- }
- public class CashRebate:CashSuper //打折
- {
- private double moneyRebate = 1d;
- public CashRebate(string moneyRebate)
- {
- this.moneyRebate = double.Parse(moneyRebate);
- }
- public override double acceptCash(double money)
- {
- return money * moneyRebate;
- //throw new Exception("The method or operation is not implemented.");
- }
- }
- public class CashReturn:CashSuper 买多少返多少.
- {
- private double moneyCondition = 0.0d;
- private double moneyReturn = 0.0d;
- public CashReturn(string moneyCondition, string moneyReturn)
- {
- this.moneyCondition = double.Parse( moneyCondition);
- this.moneyReturn = double.Parse( moneyReturn);
- }
- public override double acceptCash(double money)
- {
- double result = money;
- if (money >= moneyCondition)
- {
- return money- Math.Floor (money / moneyCondition ) * moneyReturn ;
- }
- //throw new Exception("The method or operation is not implemented.");
- return result;
- }
- }
OK,我们的算法已经出来了
现在我们要构建上图UML图中的 环境变量Context
- public class CashContext
- {
- CashSuper cs = null;
- public CashContext(CashSuper cs)
- {
- this.cs = cs;
- }
- public double Result(double money)
- {
- return cs.acceptCash(money);
- }
- }
好了。
客户端调用代码
- class Program
- {
- static void Main(string[] args)
- {
- CashContext cs = new CashContext(new CashRebate("0.8"));
- Console.Write(cs.Result(100));
- Console.ReadLine();
- }
- }
这个博客将的很详细 http://www.cnblogs.com/justinw/articles/641414.html
下面是转载自上博客
前面说了那么多,现在终于到了正式介绍我们今天的主角的时候啦!此刻心情真是好激动啊!其实我们在前面就是使用Strategy模式帮Joe度过了难过,真不知道他发了奖金后要怎么感谢我们啊。OK!下面先看看官方的定义:
The Strategy Pattern defines a family of algorithms,encapsulates each one,and makes them interchangeable. Strategy lets the algorithm vary independently from clients that use it.(策略模式定义了一系列的算法,并将每一个算法封装起来,而且使它们还可以相互替换。策略模式让算法独立于使用它的客户而独立变化。)
Context(应用场景):
l 需要使用ConcreteStrategy提供的算法。
l 内部维护一个Strategy的实例。
l 负责动态设置运行时Strategy具体的实现算法。
l 负责跟Strategy之间的交互和数据传递。
Strategy(抽象策略类):
l 定义了一个公共接口,各种不同的算法以不同的方式实现这个接口,Context使用这个接口调用不同的算法,一般使用接口或抽象类实现。
ConcreteStrategy(具体策略类):
l 实现了Strategy定义的接口,提供具体的算法实现。
应用场景和优缺点
上面我们已经看过了Strategy模式的详细介绍,下面我们再来简单说说这个模式的优缺点吧!怎么说呢,人无完人,设计模式也不是万能的,每一个模式都有它的使命,也就是说只有在特定的场景下才能发挥其功效。我们要使用好模式,就必须熟知各个模式的应用场景。
对于Strategy模式来说,主要有这些应用场景:
1、 多个类只区别在表现行为不同,可以使用Strategy模式,在运行时动态选择具体要执行的行为。(例如FlyBehavior和QuackBehavior)
2、 需要在不同情况下使用不同的策略(算法),或者策略还可能在未来用其它方式来实现。(例如FlyBehavior和QuackBehavior的具体实现可任意变化或扩充)
3、 对客户(Duck)隐藏具体策略(算法)的实现细节,彼此完全独立。
对于Strategy模式来说,主要有如下优点:
1、 提供了一种替代继承的方法,而且既保持了继承的优点(代码重用)还比继承更灵活(算法独立,可以任意扩展)。
2、 避免程序中使用多重条件转移语句,使系统更灵活,并易于扩展。
3、 遵守大部分GRASP原则和常用设计原则,高内聚、低偶合。
对于Strategy模式来说,主要有如下缺点:
1、 因为每个具体策略类都会产生一个新类,所以会增加系统需要维护的类的数量。
备注:关于场景和优缺点,上面肯定说得不够全面,欢迎大家来补充。
.NET框架里的应用
Strategy模式的应用非常广泛,也许大家有意无意之间一直都在使用。这里举一个.NET框架里使用Strategy模式的例子,象这样的例子其实还有很多,只要大家细心体会就一定会发现的。
如果写过程序,那么ArrayList类肯定都会用过吧,那么它的Sort方法想必大家也一定不陌生了。Sort方法的定义如下:
public virtual void Sort (IComparer comparer)
可以看到Sort方法接收一个IComparer类型的参数,那么这个IComparer接口是做什么用的呢?下面我们看一段程序,下面的代码示例演示如何使用默认比较器和一个反转排序顺序的自定义比较器,对 ArrayList 中的值进行排序。(完全引自MSDN:ms-help://MS.MSDNQTR.v80.chs/MS.MSDN.v80/MS.NETDEVFX.v20.chs/cpref2/html/M_System_Collections_ArrayList_Sort_1_a2d90598.htm)
- using System;
- 2using System.Collections;
- 3
- 4public class SamplesArrayList {
- 5
- 6 public class myReverserClass : IComparer {
- 7
- 8 // Calls CaseInsensitiveComparer.Compare with the parameters reversed.
- 9 int IComparer.Compare( Object x, Object y ) {
- 10 return( (new CaseInsensitiveComparer()).Compare( y, x ) );
- 11 }
- 12
- 13 }
- 14
- 15 public static void Main() {
- 16
- 17 // Creates and initializes a new ArrayList.
- 18 ArrayList myAL = new ArrayList();
- 19 myAL.Add( "The" );
- 20 myAL.Add( "quick" );
- 21 myAL.Add( "brown" );
- 22 myAL.Add( "fox" );
- 23 myAL.Add( "jumps" );
- 24 myAL.Add( "over" );
- 25 myAL.Add( "the" );
- 26 myAL.Add( "lazy" );
- 27 myAL.Add( "dog" );
- 28
- 29 // Displays the values of the ArrayList.
- 30 Console.WriteLine( "The ArrayList initially contains the following values:" );
- 31 PrintIndexAndValues( myAL );
- 32
- 33 // Sorts the values of the ArrayList using the default comparer.
- 34 myAL.Sort();
- 35 Console.WriteLine( "After sorting with the default comparer:" );
- 36 PrintIndexAndValues( myAL );
- 37
- 38 // Sorts the values of the ArrayList using the reverse case-insensitive comparer.
- 39 IComparer myComparer = new myReverserClass();
- 40 myAL.Sort( myComparer );
- 41 Console.WriteLine( "After sorting with the reverse case-insensitive comparer:" );
- 42 PrintIndexAndValues( myAL );
- 43
- 44 }
- 45
- 46 public static void PrintIndexAndValues( IEnumerable myList ) {
- 47 int i = 0;
- 48 foreach ( Object obj in myList )
- 49 Console.WriteLine( "/t[{0}]:/t{1}", i++, obj );
- 50 Console.WriteLine();
- 51 }
- 52
- 53}
- 54
- 55
- 56/**//*
- 57This code produces the following output.
- 58The ArrayList initially contains the following values:
- 59 [0]: The
- 60 [1]: quick
- 61 [2]: brown
- 62 [3]: fox
- 63 [4]: jumps
- 64 [5]: over
- 65 [6]: the
- 66 [7]: lazy
- 67 [8]: dog
- 68
- 69After sorting with the default comparer:
- 70 [0]: brown
- 71 [1]: dog
- 72 [2]: fox
- 73 [3]: jumps
- 74 [4]: lazy
- 75 [5]: over
- 76 [6]: quick
- 77 [7]: the
- 78 [8]: The
- 79
- 80After sorting with the reverse case-insensitive comparer:
- 81 [0]: the
- 82 [1]: The
- 83 [2]: quick
- 84 [3]: over
- 85 [4]: lazy
- 86 [5]: jumps
- 87 [6]: fox
- 88 [7]: dog
- 89 [8]: brown
- 90*/
怎么样,大家看出来了吧,其实在这段代码里,ArrayList相当于Strategy模式中的Context(应用场景)部分,而IComparer相当于Strategy(抽象策略类)部分,myReverserClass相当于ConcreteStrategy(具体策略类)部分。我们这里抛开myReverserClass类的Compare方法如何具体实现不谈,我们只要知道这是一个具体策略类,它提供了应用场景需要的具体算法,它实现了抽象策略类接口,而应用场景通过抽象策略类动态调用到了具体策略类中的算法。哈!所以这是一个十分典型的Strategy模式的应用。
基于这个符合Strategy模式的结构,我们还可以提供很多种自定义的具体策略类的实现,只要这些类实现了IComparer接口,就可以在运行时动态设置给ArrayList类的Sort方法,在Sort方法中会根据具体策略类实现的比较算法规则来对ArrayList中的数据进行排序。
最后一个设计原则
关于Strategy模式的故事讲到这里,应该基本OK啦!下面我们再聊些更高层次的东西。什么是更高层次的东西?嘿!当然是设计原则了!在前面总结Strategy模式的优点的时候我们提到过,Strategy模式不仅保留了继承的优点,而且还提供了更灵活的扩展能力。为什么会这样呢?Strategy模式是怎么做到这一点的呢?哈!这是因为它“上面有人”啊!谁啊?它就是我们下面要介绍的重量级设计原则:
Favor composition over inheritance.(优先使用对象组合,而非类继承)
关于组合和继承,我们只要这样来理解即可:组合是一种“HAS-A”关系,而继承是一种“IS-A”关系。很明显“HAS-A”要比“IS-A”更灵活一些。也就是说在创建系统的时候,我们应该优先使用对象组合,因为它不仅可以给你提供更多灵活性和扩展性,而且还使你可以在运行时改变行为(组合不同的对象),这简直是酷毙了!但是也不是说继承就是不能用,只是说应该把继承应用在相对更稳定,几乎没有变化的地方。