商场搞活动(打折、满减)
先用简单工厂模式实现一遍:
收费抽象类:
package factory_strategy;
public abstract class CashSuper {
public double acceptCash(double money){
return 0.0;
}
}
正常收费子类:
package factory_strategy;
public class CashNormal extends CashSuper {
@Override
public double acceptCash(double money) {
return money;
}
}
满减收费子类:
package factory_strategy;
public class CashReturn extends CashSuper {
private double moneyCondition = 0.0;
private double moneyReturn = 0.0;
public CashReturn(double moneyCondition, double moneyReturn) {
this.moneyCondition = moneyCondition;
this.moneyReturn = moneyReturn;
}
@Override
public double acceptCash(double money) {
double result = money;
if(money >= moneyCondition){
result = money - (Math.floor(money/moneyCondition))*moneyReturn;
}
return result;
}
}
这里注意:
向上取整用Math.ceil(double a)
向下取整用Math.floor(double a)
double a=35;
double b=20;
double c = a/b;
System.out.println("c===>"+c); //1.75
System.out.println("c===>"+Math.ceil(c)); //2.0
System.out.println(Math.floor(c)); //1.0
打折收费类:
package factory_strategy;
public class CashRebate extends CashSuper {
private double moneyRebate = 1.0;
public CashRebate(double moneyRebate) {
this.moneyRebate = moneyRebate;
}
@Override
public double acceptCash(double money) {
return money*moneyRebate;
}
}
工厂类:
package factory_strategy;
public class factory {
public static CashSuper Getmodel(String type){
CashSuper cs = null;
switch (type){
case "正常收费":
cs = new CashNormal();
break;
case "满300减30":
cs = new CashReturn(300,30);
break;
case "打八折":
cs = new CashRebate(0.8);
break;
}
return cs;
}
}
客户端:
package factory_strategy;
public class Maintest {
public static void main(String[] args) {
double total = 0.0;
CashSuper cs = factory.Getmodel("满300减30");
System.out.println(cs.acceptCash(590));
CashSuper cs1 = factory.Getmodel("打八折");
System.out.println(cs1.acceptCash(80));
}
}
如果需要增加打五折和满500减60的活动,只需要在工厂中加两个条件
如果需要添加一种新的促销手段,满100积分10点,需要加一个积分算法,继承CashSuper,构造方法中有两个参数(条件和返点),再到工厂中添加分支条件即可。
简单工厂虽然可以解决这个问题,但是这个模式只是解决了对象的创建问题,而且由于工厂本身包括了所有的收费方式,商场可能是经常性地更改打折额度和满减活动,每次维护或者扩展收费方式需要改动工厂,代码需要重新编译部署,不是最好的办法。
策略模式:
策略模式定义了算法家族,分别封装起来,让它们之间可以相互替换,此模式让算法的变化不会影响到使用算法的用户。
原来的CashSuper,CashNormal,CashRebate和CashReturn都不用改,只要加一个CashContext,并改一下客户端就好
CashContext(这里结合了简单工厂模式,在CashContext中增加了判断算法的过程)
package factory_strategy;
public class CashContext {
CashSuper cs;
public CashContext(String type) {
switch (type){
case "正常收费":
cs = new CashNormal();
break;
case "满300减30":
cs = new CashReturn(300,100);
break;
case "打八折":
cs = new CashRebate(0.8);
break;
}
}
public double GetResult(double money){
return cs.acceptCash(money);
}
}
客户端:
package factory_strategy;
public class Maintest2 {
public static void main(String[] args) {
CashContext cc = new CashContext("打八折");
System.out.println(cc.GetResult(400));
}
}
原来的简单工厂模式:
CashSuper cs = factory.Getmodel("打八折");
策略模式和简单工厂模式:
CashContext cc = new CashContext("打八折");
简单工厂模式需要让客户端认识两个类,CashSuper和factory,而策略模式与简单工厂的结合,只需要让客户端认识一个类CashContext就可以,耦合度降低。在客户端实例化的是CashContext的对象,调用的是CashContext的GetResult,具体的收费算法彻底地与客户端分离,连算法的父类CashSuper都不让客户端认识了。