简单工厂与策略模式

     时间过得好快,不知不觉又到了写博客的time了;这次简单介绍一些简单工厂、策略模式,还有他们的区别和联系,恩,进入正题:

抽象理论借助具体实例更有助于理解,这次借助我们熟知的“商场促销”,效果图:      

两个模式相同的代码部分: 

 //客户端
        double total=0.0d;
        private void Form1_Load(object sender, EventArgs e)
        {
            cmdCount.Items.AddRange(new object[] { "正常收费", "打八折", "打七折", "打五折" });

            cmdCount.SelectedIndex = 0;
        }
        //现金收费抽象类
        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)
            {
                //打折收费,初始化时输入折扣率:如0.8
                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;
            }
        }

   CashSuper、CashNormal、CashRebate、CahReturn是具体的子类,他们里面的acceptCash方法是对CashSuper.acceptCash这一虚方法的重写,使其变成带有各自Signet的方法 。               

简单工厂模式

      创建型模式 ,它关注对象创建,提供创建对象的接口. 
  一个工厂类,负责根据不同的打折优惠方法来使用不同的子类,调用相应的方法计算结果、显示信息。

   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"打八折":
                        CashRebate cr2 = new CashRebate("0.8");
                        cs = cr2;
                        break;
                }
                return cs;
            }
        }
        private void btnSure_Click(object sender, EventArgs e)
        {
            //简单工厂模式,根据下拉列表框生成相应的对象
            CashSuper csuper = CashFactory.createCashAccept(cmdCount.SelectedItem.ToString());
            double totalPrices = 0d;
            //csuper自带对象,用相应的acceptCash方法计算
            totalPrices = csuper.acceptCash(Convert.ToDouble(txtprice.Text)
                * Convert.ToDouble(txtNum.Text));

            total = total + totalPrices;
            //显示在listbox中
            lstSum.Items.Add("单价:" + txtprice.Text + "数量" + txtNum.Text + ""
                + cmdCount.SelectedItem + "合计" + totalPrices.ToString());
           //显示总计
            lblSum.Text = total.ToString();
        }

     违反了“开闭原则”:由于工厂类集中了所有实例的创建逻辑,违反了高内聚责任分配原则(GRASP职责分配原则),将全部创建逻辑集中到了一个工厂类中;它所能创建的类只能是事先考虑到的,如果需要添加新的类,则就需要改变工厂类,很难避免模块功能的蔓延,对系统的维护和扩展非常不利。

策略模式

     对象行为型模式 ,它关注行为和算法的封装 ,通常把一个系列的算法封装到一系列的策略类里面
   它定义一系列的算法,并对算法进行封装,算法间可以相互替换。把算法的责任和算法本身分割开委派给不同的对象管理。算法可独立于使用它的客户而变化。 改模式中应当由客户端自己决定在什么情况下使用什么具体策略角色。
<span style="font-family:KaiTi_GB2312;font-size:18px;">  private void btnSure_Click(object sender, EventArgs e)</span><span style="font-family: Arial; font-size: 14px;">
        {
            CashContext cc = null;
            //下拉列表,相应策略、传人
            switch (cmdCount .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(txtNum.Text) * Convert.ToDouble(txtprice.Text));

            total = total + totalPrices;
            lstSum.Items.Add("单价" + txtprice.Text + "数量" + txtNum.Text
                + " " + cmdCount.SelectedItem + "合计:" + total.ToString());
            lblSum.Text = total.ToString();
        }
        class CashContext
        {
            //声明一个cashsuper对象
            private CashSuper cs;
            //传入具体收费策略
            public CashContext (CashSuper csuper)
            {
                this.cs = csuper;
            }
            //根据策略、运用方法、计算结果
            public double GetResult(double money)
            {
                return cs.acceptCash(money);
            }
        }
</span>
        策略模式并不决定在何时使用何种算法,算法的选择由客户端来决定。这在一定程度上提高了系统的灵活性,但是客户端需要理解所有具体策略类之间的区别,以便选择合适的算法,这也是策略模式的缺点之一,在一定程度上增加了客户端的使用难度。并且 Strategy和Context之间的通信开销、策略模式将造成产生很多策略类等等不足之处使得策略模式在某些方面存在缺陷。 
    简单工厂模式和策略模式各有优缺,取长补短是人类的智慧。

简单工厂和策略模式的结合

      private void btnSure_Click(object sender, EventArgs e)
        {
            //将相应的算法字符串传人cashcontext对象中
            CashContext csuper = new CashContext(cmdCount.SelectedItem.ToString());
            double totalPrices = 0d;
            //计算总价
            totalPrices = csuper.GetResult(Convert.ToDouble(txtNum.Text) * Convert.ToDouble(txtprice.Text));
            total = total + totalPrices;
            //显示
            lstSum.Items.Add("单价" + txtprice.Text + "数量" + txtNum.Text
                + " " + cmdCount.SelectedItem + "合计:" + total.ToString());
            lblSum.Text = total.ToString();
        }

        class CashContext
        {
            //声明一个cashsuper对象
             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);
            }
        }
很不错的一个链接:介绍策略模式的
http://blog.csdn.net/hguisu/article/details/7558249  最后的例子亮了闭嘴
    吃饭,策略模式的做法:有几种方案供你选择,选择去餐厅好呢还是自己做,完全由人自行决定去构建吃饭方案(你自己需要去买餐厅,或者做饭)。而工厂模式是你决定哪种吃饭方案后,不用关注这吃饭方案怎么给你创建,也就是说你告诉我方案的名称就可以了,然后由工厂代替你去构建具体方案(工厂代替你去做饭)。
thanks for your time微笑
评论 14
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值