zoukankan      html  css  js  c++  java
  • 设计模式——策略模式

      策略模式其实很想一个简单工厂模式的再封装,简单工厂模式,在工厂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

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

  • 相关阅读:
    Convert to a source folder or rename it.
    git revert 后悔了 还原修改前的版本 + git 常用命令
    android switch语句报错:case expressions must be constant expressions
    解读ContentResolver和ContentProvider
    sdk命令
    向Android模拟器中批量导入通讯录联系人
    Rational Rose2007下载安装教程以及问题处理
    java代码打包成jar以及转换为exe
    Timusoj 1982. Electrification Plan
    poj 3254 Corn Fields
  • 原文地址:https://www.cnblogs.com/Smilodon/p/3089738.html
Copyright © 2011-2022 走看看