戏说面向对象程序设计(C#版) 第七章 工厂不好用了?

第七章      工厂不好用了?

内容来自dedecms

  织梦内容管理系统

小菜心里想:“大鸟要我做的是一个商场收银软件,营业员根据客户购买商品单价和数量,向客户收费。这个很简

内容来自dedecms

单,两个文本框,输入单价和数量,再用个列表框来记录商品的合计,最终用一个按钮来算出总额就可,对,还需要一 织梦好,好织梦

个重置按钮来重新开始,不就行了?!” 织梦好,好织梦

  本文来自织梦

代码样例(可使用):

本文来自织梦

  内容来自dedecms

商场收银系统v1.0关键代码如下: 内容来自dedecms

//声明一个double变量total来计算总计

织梦内容管理系统

doubletotal = 0.0d; dedecms.com

private    voidbtnOk_Click(objectsender,       EventArgse)

本文来自织梦

{ dedecms.com

//声明一个double变量totalPrices来计算每个商品的单价(txtPrice)*数量(txtNum)后

织梦好,好织梦

的合计 本文来自织梦

doubletotalPrices =       Convert.ToDouble(txtPrice.Text) * 内容来自dedecms

Convert.ToDouble(txtNum.Text); copyright dedecms

//将每个商品合计计入总计 内容来自dedecms

    total = total + totalPrices;

织梦好,好织梦

//在列表框中显示信息 织梦好,好织梦

    lbxList.Items.Add( 织梦好,好织梦

"单价:"+ txtPrice.Text +          " 数量:"+  内容来自dedecms

        txtNum.Text +   " 合计:"+ totalPrices.ToString()); 内容来自dedecms

//在lblResult标签上显示总计数 dedecms.com

    lblResult.Text = total.ToString(); dedecms.com

} 本文来自织梦

 

织梦好,好织梦

       “大鸟,”小菜叫道,“来看看,这不就是你要的收银软件吗?我不到半小时就搞定了。”

织梦好,好织梦

       “哈哈,很快吗,”大鸟说着,看了看小菜的代码。接着说:“现在我要求商场对商品搞活动,所有的商品打8 折。” dedecms.com

       “那不就是在totalPrices 后面乘以一个0.8 吗?”

copyright dedecms

       “小子,难道商场活动结束,不打折了,你还要再把程序改写代码再去把所有机器全部安装一次吗?再说,我现在还 内容来自dedecms

有可能因为周年庆,打五折的情况,你怎么办?” copyright dedecms

小菜不好意思道:“啊,我想得是简单了点。其实只要加一个下拉选择框就可以解决你说的问题。”

copyright dedecms

大鸟微笑不语。 内容来自dedecms

 

内容来自dedecms

商场收银系统v1.1 关键代码如下:

dedecms.com

 

织梦内容管理系统

doubletotal = 0.0d;

织梦内容管理系统

private    voidbtnOk_Click(objectsender,       EventArgse) 织梦好,好织梦

{ dedecms.com

doubletotalPrices = 0d; 内容来自dedecms

//cbxType是一个下拉选择框,分别有“正常收费”、“打8折”、“打7折”和“打5折” copyright dedecms

switch(cbxType.SelectedIndex) 织梦内容管理系统

    { 内容来自dedecms

case0: 织梦好,好织梦

        totalPrices = 

本文来自织梦

Convert.ToDouble(txtPrice.Text) *        Convert.ToDouble(txtNum.Text); 织梦好,好织梦

break; dedecms.com

case1: 织梦好,好织梦

        totalPrices =  dedecms.com

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

copyright dedecms

break;

dedecms.com

case2:

本文来自织梦

        totalPrices =  本文来自织梦

Convert.ToDouble(txtPrice.Text) *        Convert.ToDouble(txtNum.Text) * 0.7; 织梦好,好织梦

break; 织梦内容管理系统

case3: dedecms.com

        totalPrices = 

内容来自dedecms

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

织梦内容管理系统

break;

织梦内容管理系统

  织梦好,好织梦

    }

内容来自dedecms

    total = total + totalPrices;

织梦好,好织梦

    lbxList.Items.Add( copyright dedecms

"单价:"+ txtPrice.Text +  本文来自织梦

" 数量:"+ txtNum.Text +      " "+ cbxType.SelectedItem +  dedecms.com

" 合计:"+ totalPrices.ToString());

织梦内容管理系统

    lblResult.Text = total.ToString();

内容来自dedecms

dedecms.com

 

织梦内容管理系统

  织梦好,好织梦

} 织梦好,好织梦

        “这下可以了吧,只要我事先把商场可能的打折都做成下拉选择框的项,要变化的可能性就小多了。”小菜说道。 内容来自dedecms

        “这比刚才灵活性上是好多了,不过重复代码很多,像Convert.ToDouble(),你这里就写了8遍,而且4个分支要执 织梦好,好织梦

行的语句除了打折多少以外几乎没什么不同,应该考虑重构一下。不过还不是最主要的,现在我的需求又来了,商场的 内容来自dedecms

活动加大,需要有满300返100的促销算法,你说怎么办?”

织梦内容管理系统

        “满300返100,那要是700就要返200了?这个必须要写函数了吧?” 内容来自dedecms

          “小菜呀,看来之前教你的白教了,这里面看不出什么名堂吗?”   

dedecms.com

         “哦!我想起来了,你的意思是简单工厂模式是吧,对的对的,我可以先写一个父类,再继承它实现多个打折和返

dedecms.com

利的子类,利用多态,完成这个代码。”

织梦内容管理系统

         “你打算写几个子类?” 织梦内容管理系统

          “根据需求呀,比如8折、7折、5折、满300送100、满200送50……要几个写几个。” dedecms.com

        “小菜又不动脑子了,有必要这样吗?如果我现在要3折,我要满300送80,你难道再去加子类?你不想想看,这当 内容来自dedecms

中哪些是相同的,哪些是不同的?” 织梦内容管理系统

          “ 对的,这里打折基本都是一样的,只要有个初始化参数就可以了。满几送几的,需要两个参数才行,明白,现

dedecms.com

在看来不麻烦了。”

copyright dedecms

        “面向对象的编程,并不是类越多越好,类的划分是为了封装,但分类的基础是抽象,具有相同属性和功能的对象 织梦内容管理系统

的抽象集合才是类    。打一折和打九折只是形式的不同,抽象分析出来,所有的打折算法都是一样的,所以打折算法应该

copyright dedecms

是一个类。好了,空话已说了太多,写出来再是真的懂。” 本文来自织梦

大约1个小时后,小菜交出了第三份的作业 织梦好,好织梦

  织梦内容管理系统

商场收银系统v1.3关键代码如下 织梦好,好织梦

  本文来自织梦

//现金收取父类

织梦好,好织梦

abstract    class   CashSuper

内容来自dedecms

{

织梦好,好织梦

}

本文来自织梦

  织梦好,好织梦

 //抽象方法:收取现金,参数为原价,返回为当前价

dedecms.com

public   abstract    doubleacceptCash(doublemoney);

织梦内容管理系统

//正常收费,继承CashSuper 内容来自dedecms

class   CashNormal: CashSuper copyright dedecms

{ dedecms.com

public   override    doubleacceptCash(doublemoney) 织梦好,好织梦

    { 本文来自织梦

returnmoney; copyright dedecms

    }

内容来自dedecms

}

内容来自dedecms

//打折收费,继承CashSuper 织梦内容管理系统

class   CashRebate: CashSuper 本文来自织梦

{ 本文来自织梦

private    doublemoneyRebate = 1d;

本文来自织梦

//初始化时,必需要输入折扣率,如八折,就是0.8 织梦内容管理系统

publicCashRebate(stringmoneyRebate)

dedecms.com

    { copyright dedecms

this.moneyRebate =  double.Parse(moneyRebate);

织梦内容管理系统

    } dedecms.com

 

copyright dedecms

public   override    doubleacceptCash(doublemoney)

织梦内容管理系统

    { 内容来自dedecms

returnmoney * moneyRebate; 内容来自dedecms

    } dedecms.com

} 本文来自织梦

//返利收费,继承CashSuper 本文来自织梦

class   CashReturn:  CashSuper 内容来自dedecms

{ 织梦好,好织梦

private    doublemoneyCondition = 0.0d; 本文来自织梦

private    doublemoneyReturn = 0.0d; 内容来自dedecms

//初始化时必须要输入返利条件和返利值,比如满300返100,

织梦好,好织梦

//则moneyCondition为300,moneyReturn为100

dedecms.com

publicCashReturn(stringmoneyCondition,    stringmoneyReturn) copyright dedecms

    { copyright dedecms

this.moneyCondition =   double.Parse(moneyCondition); 内容来自dedecms

this.moneyReturn =  double.Parse(moneyReturn);

本文来自织梦

    } 织梦内容管理系统

 

dedecms.com

public   override    doubleacceptCash(doublemoney)

织梦好,好织梦

    {

织梦好,好织梦

doubleresult = money; copyright dedecms

//若大于返利条件,则需要减去返利值

dedecms.com

if(money >= moneyCondition)

本文来自织梦

            result = money -     Math.Floor(money / moneyCondition) * moneyReturn;

本文来自织梦

returnresult; 内容来自dedecms

    }

本文来自织梦

} 织梦内容管理系统

//现金收取工厂

内容来自dedecms

class   CashFactory 织梦好,好织梦

{

内容来自dedecms

//根据条件返回相应的对象

织梦好,好织梦

public   static     CashSupercreateCashAccept(stringtype)

本文来自织梦

    { 织梦内容管理系统

CashSupercs = null;

dedecms.com

switch(type)

内容来自dedecms

        { 本文来自织梦

case  "正常收费": 织梦内容管理系统

                cs =   new         CashNormal();

织梦内容管理系统

break; 内容来自dedecms

case  "满300返100":

内容来自dedecms

CashReturncr1 =  new                                    CashReturn("300",           "100");

本文来自织梦

                cs = cr1;

织梦好,好织梦

break;

织梦内容管理系统

case  "打8折": 织梦内容管理系统

CashRebatecr2 =  new         CashRebate("0.8"); dedecms.com

                cs = cr2;

织梦好,好织梦

break;

织梦内容管理系统

        }

织梦内容管理系统

returncs;

本文来自织梦

    }

织梦内容管理系统

} 织梦好,好织梦

 

织梦内容管理系统

//客户端窗体程序(主要部分)

织梦内容管理系统

CashSupercsuper;//声明一个父类对象 织梦内容管理系统

doubletotal = 0.0d;

copyright dedecms

private    voidbtnOk_Click(objectsender,       EventArgse) 本文来自织梦

{

织梦内容管理系统

//利用简单工厂模式根据下拉选择框,生成相应的对象 copyright dedecms

    csuper =   CashFactory.createCashAccept(cbxType.SelectedItem.ToString());

织梦好,好织梦

doubletotalPrices = 0d; copyright dedecms

//通过多态,可以得到收取费用的结果

内容来自dedecms

    totalPrices = csuper.acceptCash(

本文来自织梦

        onvert.ToDouble(txtPrice.Text) *         Convert.ToDouble(txtNum.Text)

织梦内容管理系统

        );

织梦好,好织梦

    total = total + totalPrices; 内容来自dedecms

    lbxList.Items.Add(

织梦内容管理系统

  织梦内容管理系统

织梦好,好织梦

  织梦内容管理系统

"单价:"+ txtPrice.Text +  织梦好,好织梦

" 数量:"+ txtNum.Text +      " "+ cbxType.SelectedItem + 

织梦好,好织梦

" 合计:"+ totalPrices.ToString()); dedecms.com

    lblResult.Text = total.ToString(); 本文来自织梦

}

内容来自dedecms

代码样例(可使用)

内容来自dedecms

  本文来自织梦

      “大鸟,搞定,这次无论你要怎么改,我都可以简单处理就行了。”小菜自信满满的说。

内容来自dedecms

      “是吗,我要是需要打5 折和满500 送200 的促销活动,如何办?”

内容来自dedecms

      “只要在现金工厂当中加两个条件,在界面的下拉选项框里加两项,就OK了。” dedecms.com

      “现金工厂?!你当是生产钞票呀。是收费对象生成工厂才准确。说得不错,如果我现在需要增加一种商场促销手段,

内容来自dedecms

满100 积分10 点,以后积分到一定时候可以领取奖品如何做?”

本文来自织梦

      “有了工厂,何难?加一个积分算法,构造方法有两个参数:条件和返点,让它继承CashSuper,再到现金工厂,哦, dedecms.com

不对,       ,是收—费—对—象—生—成—工—厂里加满100 积分10 点的分支条件,再到界面稍加改动,就行了。”

织梦好,好织梦

      “嗯,不错,那我问你,如果商场现在需要拆迁,没办法,只能跳楼价销售,商场的所有商品都需要打8 折,打折后

织梦好,好织梦

的价钱再每种商品满300 送50,最后计总价的时候,商场还满1000 送200,你说如何办?” 织梦好,好织梦

      “搞没搞错哦,这商场不如白送得了,哪有这样促销的?老板跳楼时估计都得赤条条的了。” copyright dedecms

        “商场大促销你还不高兴呀!当然,你是软件开发者,客户老是变动需求的确不爽,但你不能不让客户提需求呀,我 copyright dedecms

不是说过吗,需求的变更是必然!所以开发者应该的是考虑如何让自己的程序更能适应变化,而不是抱怨客户的无理,

本文来自织梦

客户不会管程序员加班时的汗水          ,也不相信程序员失业时的眼泪        ,因为客户自己正在为自己的放血甩卖而流泪呀。” 织梦内容管理系统

大鸟接着说:“简单工厂模式虽然也能解决这个问题,但的确不是最好的办法,另外由于商场是可能经常性的更改 内容来自dedecms

打折额度和返利额度,每次更改都需要改写代码重新编译部署真的是很糟糕的处理方式,面对算法的时常变动,应该有 内容来自dedecms

更好的办法。好好去研究一下设计模式吧,推荐你看一本书,《深入浅出设计模式》,或许你看完第一章,就会有解决 copyright dedecms

办法了。       ” 织梦好,好织梦

小菜进入了沉思中……

copyright dedecms

  织梦内容管理系统

本例C#源代码CashAcceptSystem.rar

dedecms.com

 

内容来自dedecms

另:建议大家去阅读《深入浅出设计模式》,第一章下载,本人非常喜欢这本书的风格,这是真正的做到了深入浅出呀。

copyright dedecms

我也希望自己可以用类似的方式讲述问题。 织梦好,好织梦

本文还有一个用意是对一些初学者,可以考虑一下大鸟提出的问题,在我的下一篇《小菜编程成长记           八》出来之前,改

内容来自dedecms

写我的源代码,实现更灵活更方便的商场收银程序共享给大家讨论,或许您写的东东比我写的还要好,那样就大家都有 本文来自织梦

提高了。程序不是看出来的,是写出来的。好好加油!

织梦内容管理系统

本文来自织梦

精彩推荐
热点内容
最近更新