您的位置:首页 > 其它

大话设计模式-第02章 商场促销--策略模式

2016-06-04 00:11 369 查看
第02章商场促销--策略模式

2.1 商场收银软件

版本1:

    double total = 0.0d;

    private void btnOk_Click(object sender, EventArgs e)

    {

        double totalPrices = Convert.ToDouble(txtPrice.text) * Convert.ToDouble(txtNum.Text);

        total = total + totalPrices;

        lbxList.Items.Add(“单价:” + txtPrice.Text + “数量:” + txtNum.Text + “合计:” + totalPrices.ToString());

        lblResult.Text = total.ToString();

    }

2.2 增加打折

版本2:

    private void Forml_Load(object sender, EventArgs e)

    {

        cbxType.Items.AddRange(new object[] {“正常收费”,“打八折”,“打七折”,“打五折”});

        cbxType.SelectedIndex = 0;

    }

    private void btnOk_Click(object sender, EventArgs e)

    {

        double totalPrices = 0d;

        switch (cbxType.SelectedIndex)

        {

            case 0:

                totalPrices = Convert.ToDouble(txtPrice.Text) * Convert.ToDouble(txtNum.Text);

                break;

            case 1:

                totalPrices = Convert.ToDouble(txtPrice.Text) * Convert.ToDouble(txtNum.Text) * 0.8;

                break;

            case 2:

                totalPrices = Convert.ToDouble(txtPrice.Text) * Convert.ToDouble(txtNum.Text) * 0.7;

                break;

            case 3:

                totalPrices = Convert.ToDouble(txtPrice.Text) * Convert.ToDouble(txtNum.Text) * 0.5;

                break;

        }

        total = total + totalPrices;

        lbxList.Items.Add(“单价:” + txtPrice.Text + “数量:” + txtNum.Text + “合计:” + totalPrices.ToString());

        lblResult.Text = total.ToString();

    }

上述代码:

    1:重复代码过多;

    2:如果要支持新的折扣算法,如满*返现等,则很难扩展。

2.3 简单工厂实现

    面向对象的编程,并不是类越多越好,类的划分是为了封装,但分类的基础是抽象,具有相同属性和功能的对象的抽象集合才是类。

rebate  |ˈriːbeɪt| noun返款、折扣

cash |kæʃ| noun
Uncountable 现金

代码3:

现金收费抽象类

    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;

        }

    }

现金收费工厂类

    class CashFactory

    {

        public static CashSuper createCashAccept(string type)

        {

            CashSuper cs = null;

            switch(type)

            {

                case “正常收费”;

                    cs = new CashNormal();

                    break;

                case “满300返100”;

                    CashReturn cr1 = new CashReturn(“300”, “100”);

             
      cs = cr1;

                    break;

                case “打8折”;

                    CashRebate cr2 = new CashRebate(“0.8”);

             
      cs = cr2;

                    break;

            }

            return cs;

        }

    }

客户端程序主要部分

    double total = 0.0d;

    private void btnOk_Click(object sender, EventArgs e)

    {

        CashSuper super = CashFactory.createCashAccept(cbxType.selectedItem.ToString());

        double totalPrices = 0d;

        totalPrices = csuper.acceptCash(Convert.ToDouble(txtPrice.Text) * Convert.ToDouble(txtNum.Text));

        total = total + totalPrices;

        lbxList.Items.Add(“单价:” + txtPrice.Text + “数量:” + txtNum.Text + “合计:” + totalPrices.ToString());

        lblResult.Text = total.ToString();

    }

上面的代码虽然极大的优化了代码,但仍然难以适应变化。

2.4 策略(Strategy)模式

strategy |ˈstrætədʒi| noun战略、策略

algorithm |ˈælgərɪðəm| noun算法 

context |ˈkɒntekst| noun环境、上下文

    策略模式(Strategy):定义了算法家族,分别封装起来,让他们之间可以相互替换,此模式让算法的变化,不会影响到使用算法的客户。

    Strategy类,定义所有支持的算法的公共接口

        //抽象算法类

        abstract class Strategy

        {

            //算法方法

            public abstract void AlgorithmInterface();

        }

    ConcreteStrategy,封装了具体的算法或行为,继承于Strategy

        //具体算法A

        class ConcreteStrategyA : Strategy

        {

            //算法A实现方法

            public override void AlgorithmInterface()

            {

                console.WriteLine(“算法A实现”);

            }

        }

        //具体算法B

        class ConcreteStrategyB : Strategy

        {

            //算法B实现方法

            public override void AlgorithmInterface()

            {

                console.WriteLine(“算法B实现”);

            }

        }

        //具体算法C

        class ConcreteStrategyC : Strategy

        {

            //算法C实现方法

            public override void AlgorithmInterface()

            {

                console.WriteLine(“算法C实现”);

            }

        }

    Context, 用一个ConcreteStrategy来配置,维护一个对Strategy对象的引用。

        //上下文

        class Context

        {

            Strategy strategy;

            public Context(Strategy strategy)

            {

                this.strategy = strategy;

            }

            //上下文接口

            public void ContextInterface()

            {

                strategy.AlgorithmInterface();

            }

        }

    客户端代码

        static void Main(string[] args)

        {

            Context context;

            context = new Context(new ConcreteStrategyA());

            context.ContextInterface();

            context = new Context(new ConcreteStrategyB());

            context.ContextInterface();

            context = new Context(new ConcreteStrategyC());

            context.ContextInterface();

            Console.Read();

        }

2.5 策略模式实现

    class CashContext

    {

        private CashSuper cs;

        public CashContext(CashSuper super)

        {

            this.cs = csuper;

        }

        public double GetResult(double money)

        {

            return cs.acceptCash(money);

        }

    }

客户端主要代码

    double total = 0.0d;//用于总计

    private void btn0k_Click(object sender, EventArgs e)

    {

        CashContext cc = null;

        switch (cbxType.SelectedItem.ToString())

        {

            case “正常收费”:

                cc = new CashContext(new CashNormal());

                break;

            case “满300返100”:

                cc = new CashContext(new CashReturn(“300”, “100”));

                break;

            case “打8折”:

                cc = new CashContext(new CashRebate(“0.8”));

                break;

        }

        double totalPrices = 0d;

        totalPrices = cc.GetResult(Convert.ToDouble(txPrice.Text) * Convert.ToDouble(txtNum.Text));

        total = total + totalPrices;

        lbxList.Items.Add(“单价:” + txtPrice.Text + “数量:” + txtNum.Text + “合计:” + totalPrices.ToString());

        lblResult.Text = total.ToString();

    }

上面的代码也可以通过简单工厂模式把判断的过程从客户端转移走。这样客户端只需要“认识”简单工厂类即可。

2.7 策略模式解析

    策略模式是一种定义一系列算法的方法,从概念上来看,所有这些算法完成的都是相同的工作,只是实现不同,它可以以相同的方式调用所有的算法,减少了各种算法类与使用算法类之间的耦合。

    策略模式的抽象Strategy类层次为Context定义了一系列可供重用的算法或行为。继承有助于析取这些算法中的公共功能。另外简单工厂也简化了单元测试。

    基本的策略模式中,选择所用具体实现的职责有客户端对象承担,并转给策略模式的Context对象。这本身并没有解除客户端需要选择判断的压力,而策略模式与简单工厂模式相结合后,可以大大简化客户端的职责。

    但如果需要增加新的算法,依然需要对简单工厂类做修改,任何需求的变更都是需要成本的。只是成本高低有差异而已。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: