背景
接受到一个商场收银系统的续期,客户那边说需要做一个收银软件,根据客户所购买的单价和数量进行计算应该收多少钱。做完一版之后客户要求增加打折功能,然后还需要支持满减功能。
起初我的涉及思路是这样的,创建一个公共的接口根据type判断当前使用哪一种收款模式,然后选择对应的函数来计算所需要收的现金。
简单工厂模式
因为之前学习了简单工厂模式,觉得这种场景下也比较适用简单工厂模式,于是产生了以下的代码;先创建一个收费的父类。
public abstract class CashSuper {
private int nums;
private double price;
protected abstract double acceptCash(double money);
}
然后分别定义普通收款模式、打折收款模式和满减模式三个类
class NormalCash extends CashSuper {
@Override
protected double acceptCash(double money) {
return money;
}
}
class RebateCash extends CashSuper {
private double rebate;
public RebateCash(double rebate) {
this.rebate = rebate;
}
@Override
protected double acceptCash(double money) {
return money * rebate;
}
}
class ReturnCash extends CashSuper {
private double moneyCondition = 0.0;
private double moneyReturn = 0.0;
public ReturnCash(double moneyCondition, double moneyReturn) {
this.moneyCondition = moneyCondition;
this.moneyReturn = moneyReturn;
}
@Override
protected double acceptCash(double money) {
return money - Math.floor(money / moneyCondition) * moneyReturn;
}
}
然后创建一个收款工厂就可以了
class CashFactory {
public static CashSuper createAcceptCasg(int type) {
CashSuper cashSuper;
switch (type) {
case 0:
cashSuper = new NormalCash();
break;
case 1:
cashSuper = new RebateCash(0.7); // 打七折
break;
case 2:
cashSuper = new ReturnCash(100, 50); // 满100减50
break;
default:
cashSuper = new NormalCash();
}
return cashSuper;
}
}
这种模式下虽然也能解决这个需求,但是这个模式只是解决对象的创建问题,而且由于工厂本身也包括了所有的收费方式,商场是可能会经常性的更改打折额度和返利刻度,每次维护或者扩展都需要改动这个工厂,以致于代码需要重新编译部署,这真的是一种很糟糕的处理方式,所以它不是最好的办法。
策略模式
面对算法的经常性的变动,应该使用策略模式。
** 策略模式 定义了算法家族,分别封装起来,让他们之间可以互相替换,此模式让算法的变化不会影响使用时u案发的客户**
代码如下:客户端只需要调用这段代码即可完成,但是需要通过客户端判断使用哪个算法
class CashContexts {
private CashSuper cashSuper;
public CashContexts(CashSuper cashSuper) {
this.cashSuper = cashSuper;
}
public double getReesult(double money) {
return cashSuper.acceptCash(money);
}
}
客户端:
public static void main(String[] args) {
CashContexts cashContexts;
double money = 100;
int type = 0;
switch (type) {
case 0:
cashContexts = new CashContexts(new NormalCash());
break;
case 1:
cashContexts = new CashContexts(new RebateCash(0.7));
break;
case 2:
cashContexts = new CashContexts(new ReturnCash(100,50));
break;
default:
cashContexts = new CashContexts(new NormalCash());;
}
double reesult = cashContexts.getReesult(money);
System.out.println(reesult);
}
策略模式与简单工厂模式结合
class CashContextt {
private CashSuper cashSuper;
public CashContextt(Integer type) {
switch (type) {
case 0:
cashSuper = new NormalCash();
break;
case 1:
cashSuper = new RebateCash(0.7);
break;
case 2:
cashSuper = new ReturnCash(100,50);
break;
default:
cashSuper = new NormalCash();
}
}
public double getResult(double money) {
return cashSuper.acceptCash(money);
}
}
回头想一想,其实策略模式是一种定义一系列算法的方法,从概念上来看,这些方法完成的都是相同的工作,只是实现不一样,它可以额用相同的方法调用所有的算法,减少了各种算法类与实用类之间的耦合