设计模式——策略模式

  策略模式其实很想一个简单工厂模式的再封装,简单工厂模式,在工厂Factory中生产的是对象。而策略模式的上下文Context不仅创建了对象,而且直接调用了对象的计算方法,给我们返回的计算出的值。

  工厂模式,客户端需要(开发人员)需要记住父类和工厂类两个对象,通过参数创建对象,而策略模式,只需要创建context类,传入参数,调用方法就可以实现计算,少了一个类型,可以使客户端更加简洁。

  策略模式,它的本质就是用来封装算法,将本来由客户端承担的对象选择的职责,转到Context中,减少了客户端的压力。

  使用策略模式,要注意,策略模式里面的算法都是完成的相同的工作,只是这些工作实现的算法不同而已。

下面是策略模式的具体实现算法,使用的例子是一个收银台打折促销的算法

1.CashSuper类,这是一个父类,提供了一个根据策略计算出促销结果的抽象方法

 1 /// <summary>
 2     /// 现金收费抽象类
 3     /// </summary>
 4     abstract class CashSuper
 5     {
 6         /// <summary>
 7         /// 现金收取抽象方法
 8         /// </summary>
 9         /// <param name="money">原价</param>
10         /// <returns>当前价</returns>
11         public abstract double AcceptCash(double money);
12     }
CashSuper.cs

2.CashProduct,这是一系列具体实现算法的子类,继承自CashSuper父类

 /// <summary>
    /// 正常收费子类
    /// </summary>
    internal class CashNormal : CashSuper
    {
        /// <summary>
        /// 正常收费
        /// </summary>
        /// <param name="money">价格</param>
        /// <returns>原价</returns>
        public override double AcceptCash(double money)
        {
            return money;
        }
    }
    /// <summary>
    /// 打折消费子类
    /// </summary>
    internal class CashRebate : CashSuper
    {
        /// <summary>
        /// 初始化折扣为满折
        /// </summary>
        private double moneyRebate = 1d;

        public CashRebate(string moneyRebate)
        {
            //通过构造方法获取折扣
            this.moneyRebate = double.Parse(moneyRebate);
        }

        /// <summary>
        /// 进行打折计算
        /// </summary>
        /// <param name="money">价格</param>
        /// <returns>打折后价格</returns>
        public override double AcceptCash(double money)
        {
            return money * moneyRebate;
        }
    }
    /// <summary>
    /// 返利消费子类
    /// </summary>
    internal class CashReturn : CashSuper
    {
        /// <summary>
        /// 返利条件,需要达到的要求
        /// </summary>
        private double moneyCondition = 0.0d;

        /// <summary>
        /// 返利值,达到返利条件所返利的金额
        /// </summary>
        private double moneyReturn = 0.0d;

        /// <summary>
        /// 构造方法
        /// </summary>
        /// <param name="moneyCondition"></param>
        /// <param name="moneyReturn"></param>
        public CashReturn(string moneyCondition, string moneyReturn)
        {
            this.moneyCondition = double.Parse(moneyCondition);
            this.moneyReturn = double.Parse(moneyReturn);
        }
        /// <summary>
        /// 返利消费计算
        /// </summary>
        /// <param name="money">原价</param>
        /// <returns>现价</returns>
        public override double AcceptCash(double money)
        {
            double result = money;
            if (money >= moneyCondition)
            {
                result = money - Math.Floor(money / moneyCondition) * moneyReturn;
            }
            return result;
        }
    }
CashProduct.cs

3CashContext,这是策略模式中最重要的一个类,它的功能是根据策略参数运用构造方法创建子类对象,并且定义了一个方法,根据实际参数进行对象方法的运行,得到结果

 1  /// <summary>
 2     /// 上下文
 3     /// </summary>
 4     class CashContext
 5     {
 6         private CashSuper cashSuper = null;
 7 
 8         /// <summary>
 9         /// 构造方法,根据参数得到返利对象
10         /// </summary>
11         /// <param name="type">返利类型</param>
12         public CashContext(string type)
13         {
14             switch (type)
15             {
16                 case "正常收费":
17                     cashSuper=new CashNormal();
18                     break;
19                 case "满300反100":
20                     cashSuper=new CashRebate("0.8");
21                     break;
22                 case "打8折":
23                     cashSuper=new CashReturn("300","100");
24                     break;
25             }
26         }
27 
28         /// <summary>
29         /// 返利计算方法,根据对象计算出具体结果
30         /// </summary>
31         /// <param name="money">原价</param>
32         /// <returns>现价</returns>
33         public double GetResult(double money)
34         {
35             return cashSuper.AcceptCash(money);
36         }
37     }
CashContext.cs

4.客户端代码,因为大部分任务都给CashContext去做了,所以客户端没啥可做的,就创建了一个CashContext类用于子类对象的创建,兵器调用CashContext的计算方法得到结果

1   private void btnResult_Click(object sender, EventArgs e)
2         {
3             //根据下拉框的具体返利类型得到对象
4             var cashContext=new CashContext(cbxType.SelectedItem.ToString());
5             //根据价格和数量获得采取了策略后的总价
6             var totalPrice = cashContext.GetResult(Convert.ToInt32(txtPrice.Text)*Convert.ToInt32(txtNum.Text));
7             //得到结果
8             lbResult.Text = totalPrice.ToString(CultureInfo.InvariantCulture);
9         }
StrategyDeafult

                                                        以上内容部分参考程杰的《大话设计模式》一书

posted @ 2013-05-20 22:28  Kitten Zhang  阅读(134)  评论(0编辑  收藏  举报