【设计模式】(一)-简单工厂模式和策略模式

前言

最近开始和春哥,张铎 ,银平讨论设计模式,成立了一个小菜变大鸟的小组,每天讨论一个模式,并且把这个模式搞懂,每学一个新的模式,再回顾一下之前学的模式。这两天学了简单工厂模式和策略模式,发现两个模式有很多相同之处,下面用商场促销的例子来对两个模式总结一下。

简单工厂模式

1.首先建立一个抽象类,用以子类继承,定义了抽象方法 acceptCash() 方法传入参数 money

abstract class CashSuper
    {
        public abstract double acceptCash(double money);
    }

2.这里定义了三个子类,分别处理 正常收费 , 打折 , 满300返100 三种收费方法。

 class CashNormal : CashSuper
    {
        public override double acceptCash(double money)
        {
            return money;
        }

    }

        class CashRebate : CashSuper
    {
        private double rebate = 1d;
        public CashRebate(string Rebate)
        {
            rebate = Convert.ToDouble(Rebate);
        }
        public override double acceptCash(double Money)
        {
            return Money * rebate;
        }
    }



    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;
        }

    }

大话模式的第一章的简单工厂模式是用父类实现多态,这里体现的是用抽象类实现多态。
3.下面是工厂类

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

4.然后是客户端的代码

       public Form1()
        {
            InitializeComponent();
        }
        double total = 0.0d;
        private void button1_Click(object sender, EventArgs e)
        {
            CashContext csuper = new CashContext(cbxType.SelectedItem.ToString());
            double totalPrices = 0d;
            totalPrices = csuper.GetResult(Convert.ToDouble(txtPrice.Text) * Convert.ToDouble(txtNum.Text));
            total = total + totalPrices;
            lbxList.Items.Add("单价:" + txtPrice.Text +"数量:" + txtNum.Text + cbxType.SelectedItem + "合计:" + totalPrices.ToString());
            label4.Text = total.ToString();
            
        }

        private void Form1_Load(object sender, EventArgs e)
        {
            cbxType.Items.AddRange(new object[] { "正常收费", "打八折", "满300返100"});
            cbxType.SelectedIndex = 0;
        }
    }

首先创建 CashSuper 对象,调用工厂类的 createCashAccept()方法,根据传入的字符串(正常收费,打八折)返回相应的 CashSuper 对象,然后执行刚才复写的 acceptCash()方法,传入参数 money 进行计算。

优点:通过使用工厂类,外界可以从直接创建具体产品对象的尴尬局面摆脱出来,仅仅需要负责“消费”对象就可以了。而不必管这些对象究竟如何创建及如何组织的.明确了各自的职责和权利,有利于整个软件体系结构的优化。

缺点:由于工厂类集中了所有实例的创建逻辑,违反了高内聚责任分配原则,将全部创建逻辑集中到了一个工厂类中;它所能创建的类只能是事先考虑到的,如果需要添加新的类,则就需要改变工厂类了。

策略模式

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

同样的例子使用策略模式更改一下,CashSuper和三种处理方法不用更改,只需在简单工厂基础上添加 CashContext 类:

 class CashContext
    {
        private CashSuper cs;
 
        public CashContext(CashSuper csuper)
        {
            this.cs = csuper;
        }
 
        public double GetResult(double money)
        {
            return cs.acceptCash(money);
        }

客户端代码如下,将相应的策略对象作为参数传入 CashContext 对象中:

 private void button1_Click(object sender, EventArgs e)
        {
            CashContext cc = null ;
            switch(cbxType .SelectedItem.ToString())
            {
                case "正常收费":
                    cc = new CashContext (new CashNormal());
                    break ;
                case "打八折":
                    cc = new CashContext (new CashRebate("0.8"));
                    break ;
                case "满300返100":
                    cc = new CashContext (new CashReturn("300","100"));
                    break ;
            }
            double totalPrice = 0d;
            totalPrice = cc.GetResult(Convert.ToDouble(txtPrice.Text) * Convert.ToDouble(txtNum.Text));

比较简单工厂的方法知道,简单工厂需要客户端认识两个类 CashSuper 和 CashFactory ,而策略模式客户端只需要认识 CashContext 类就可以了,使得具体的收费算法彻底与客户端分离,耦合度更加降低。

策略与简单工厂结合

改造后的CashContext:将实例化具体策略的过程由客户端转移到Context类种。

class CashContext
    {
        CashSuper cs = null;

        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);
        }
    }
}

客户端端代码如下:

 public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }
        double total = 0.0d;
        private void button1_Click(object sender, EventArgs e)
        {
            CashContext csuper = new CashContext(cbxType.SelectedItem.ToString());
            double totalPrices = 0d;
            totalPrices = csuper.GetResult(Convert.ToDouble(txtPrice.Text) * Convert.ToDouble(txtNum.Text));
            total = total + totalPrices;
            lbxList.Items.Add("单价:" + txtPrice.Text +"数量:" + txtNum.Text + cbxType.SelectedItem + "合计:" + totalPrices.ToString());
            label4.Text = total.ToString();
            
        }

        private void Form1_Load(object sender, EventArgs e)
        {
            cbxType.Items.AddRange(new object[] { "正常收费", "打八折", "满300返100"});
            cbxType.SelectedIndex = 0;
        }
    }

总结

比较简单工厂的方法知道,简单工厂需要客户端认识两个类 CashSuper 和 CashFactory ,而策略模式客户端只需要认识 CashContext 类就可以了,使得具体的收费算法彻底与客户端分离,耦合度更加降低。

刚开始学,感觉学的还不够深入,如有错误,还望指教。

猜你喜欢

转载自blog.csdn.net/qq_41306240/article/details/84401898