设计模式培训之四:策略模式

查看本人文章索引请通过http://www.cnblogs.com/seesea125/archive/2012/04/17/2453256.html

一、定义

策略模式定义了一系列的算法,并将每一个算法封装起来,而且使它们还可以相互替换。策略模式让算法独立于使用它的客户而独立变化。

无标题

二、概述

应用场景:

  1、 多个类只区别在表现行为不同,可以使用Strategy模式,在运行时动态选择具体要执行的行为。

  2、 需要在不同情况下使用不同的策略(算法),或者策略还可能在未来用其它方式来实现。

  3、 对客户隐藏具体策略(算法)的实现细节,彼此完全独立。

三、代码实现

需求:商场收费系统,根据商品的单价和数量,得出的总结可以"正常收费", "打八折","满300返100", "打七折", "打五折"等等。

代码如下:

abstract class CashSuper
   {
       public abstract double acceptCash(double money);
   }
   //正常收费子类
   class CashNormal : CashSuper
   {
       public override double acceptCash(double money)
       {
           return money;
       }
   }
   //打折收费子类
   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;
       }
   }
   //返利收费子类
   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)
               result = money - Math.Floor(money / moneyCondition) * moneyReturn;
           return result;
       }
   }

 


Context类:

class CashContext
    {
        private CashSuper cs;
        public CashContext(string type)
        {
            switch (type)
            { 
                case "正常收费":
                    CashNormal cs0=new CashNormal();
                    cs=cs0;
                    break;
                case "满300返100":
                    CashReturn cr1 = new CashReturn("300","100");
                    cs = cr1;
                    break;
                case "打八折":
                    CashRebate cr2 = new CashRebate("0.8");
                    cs = cr2;
                    break;
            }            
        }

        public double GetResult(double money)
        {
            return cs.acceptCash(money);
        }
    }

 

客户端调用:

CashContext csuper = new CashContext(cbxType.SelectedItem.ToString());
double totalPrices = 0d;
totalPrices = csuper.GetResult(Convert.ToDouble(txtPrice.Text) * Convert.ToDouble(txtNum.Text));

 

四、和工厂的区别:

上面代码也可以用工厂方法实现,不过策略和工厂的区别很大。

如果用工厂实现,核心工厂是这样的,其他地方代码不变:

class CashFactory
    {
        public static CashSuper createCashAccept(string type)
        {
            CashSuper cs = null;
            switch (type)
            { 
                case "正常收费":
                    cs = new CashNormal();
                    break;
                case "满300返100":
                    cs = new CashReturn("300", "100");
                    break;
                case "打八折":
                    cs = new CashRebate("0.8");
                    break;
            }
            return cs;            
        }
    }

使用工厂的时候,客户端调用

CashSuper csuper = CashFactory.createCashAccept(cbxType.SelectedItem.ToString());            
double totalPrices = 0d; //工厂模式解决方案 totalPrices = csuper.acceptCash(Convert.ToDouble(txtPrice.Text) * Convert.ToDouble(txtNum.Text));


可见两种实现,他们代码很类似,大概的只是多了一个方法

public double GetResult(double money)
{
return cs.acceptCash(money);
}


由此可见他们的区别:他们返回的内容不同,工厂是返回不同的实例给客户端,而策略的实例只是为了自己的类使用,他是根据参数返回算法的结果GetResult,因此他们区别是目的不同,一个是为了返回实例,一个是为了封装不同的算法,适应算法的变化。

posted @ 2012-05-11 23:17  赵学智  阅读(2451)  评论(4编辑  收藏  举报