系列文章导航:
四大发明之活字印刷——面向对象思想的胜利
小菜编程成长记(一 面试受挫——代码无错就是好?)
小菜编程成长记(二 代码规范、重构)
小菜编程成长记(三 复制VS复用)
小菜编程成长记(四 业务的封装)
小菜编程成长记(五 体会简单工厂模式的美妙)
小菜编程成长记(五 体会简单工厂模式的美妙)
小菜编程成长记(五 体会简单工厂模式的美妙)
小菜编程成长记(六 工厂不好用了?)
小菜编程成长记(七 用“策略模式”是一种好策略)
小菜编程成长记(八 反射——程序员的快乐!)
小菜编程成长记(九 会修电脑不会修收音机?——聊设计模式原则)
小菜编程成长记(十 三层架构,分层开发)
小菜编程成长记(十一 无熟人难办事?——聊设计模式迪米特法则)
小菜编程成长记(十二 有了门面,程序员的程序会更加体面!)
小菜编程成长记(十三 设计模式不能戏说!设计模式怎就不能戏说?)
“这下可以了吧,只要我事先把商场可能的打折都做成下拉选择框的项,要变化的可能性就小多了。”小菜说道。
“这比刚才灵活性上是好多了,不过重复代码很多,像Convert.ToDouble(),你这里就写了8遍,而且4个分支要执行的语句除了打折多少以外
几乎没什么不同,应该考虑重构一下。不过还不是最主要的,现在我的需求又来了,商场的活动加大,需要有满300返100的促销算法,你说怎么办?”
“满300返100,那要是700就要返200了?这个必须要写函数了吧?”
“小菜呀,看来之前教你的白教了,这里面看不出什么名堂吗?”
“哦!我想起来了,你的意思是简单工厂模式是吧,对的对的,我可以先写一个父类,再继承它实现多个打折和返利的子类,利用多态,完成这个代码。”
“你打算写几个子类?”
“根据需求呀,比如8折、7折、5折、满300送100、满200送50……要几个写几个。”
“小菜又不动脑子了,有必要这样吗?如果我现在要3折,我要满300送80,你难道再去加子类?你不想想看,这当中哪些是相同的,哪些是不同的?”
“对的,这里打折基本都是一样的,只要有个初始化参数就可以了。满几送几的,需要两个参数才行,明白,现在看来不麻烦了。”
“面向对象的编程,并不是类越多越好,类的划分是为了封装,但分类的基础是抽象,具有相同属性和功能的对象的抽象集合才是类 。打一折和打九折只是形式的不同,抽象分析出来,所有的打折算法都是一样的,所以打折算法应该是一个类。好了,空话已说了太多,写出来再是真的懂。”
大约1个小时后,小菜交出了第三份的作业
商场收银系统v1.3关键代码如下:
Code
//现金收取父类
abstract class CashSuper
{
//抽象方法:收取现金,参数为原价,返回为当前价
public abstract double acceptCash(double money);
}
//正常收费,继承CashSuper
class CashNormal : CashSuper
{
public override double acceptCash(double money)
{
return money;
}
}
//打折收费,继承CashSuper
class CashRebate : CashSuper
{
private double moneyRebate = 1d;
//初始化时,必需要输入折扣率,如八折,就是0.8
public CashRebate(string moneyRebate)
{
this.moneyRebate = double.Parse(moneyRebate);
}
public override double acceptCash(double money)
{
return money * moneyRebate;
}
}
//返利收费,继承CashSuper
class CashReturn : CashSuper
{
private double moneyCondition = 0.0d;
private double moneyReturn = 0.0d;
//初始化时必须要输入返利条件和返利值,比如满300返100,则moneyCondition为300,moneyReturn为100
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;
}
}
//客户端窗体程序(主要部分)
CashSuper csuper;//声明一个父类对象
double total = 0.0d;
private void btnOk_Click(object sender, EventArgs e)
{
//利用简单工厂模式根据下拉选择框,生成相应的对象
csuper = 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 + " "+cbxType.SelectedItem+ " 合计:" + totalPrices.ToString());
lblResult.Text = total.ToString();
}
代码样例(可使用)