小kim菌:菜菜,刚才我去买烧烤,满5块减2块!烧烤大叔算得手忙脚乱!
小菜菌:哈哈,买5块减2块,那买10块,减4块...
小kim菌:那买10086块呢
饥饿的小菜菌想了想,甩出一行代码。
//Math.floor:向下取整,比如Math.floor(3.5)=3, Math.floor(3.95)=3
//money/5: 总金额/满减条件,结果取整即满减倍数,再乘以满减金额,等于减的总金额
result = money - Math.floor(money/5) * 2;
小kim菌:那来个打8折呢
更饥饿的小菜菌继续想...
果然,奇怪的促销增加了...
热心市民小菜菌为了支持烧烤生意,运用设计模式大法之「策略模式」,帮烧烤大叔写了个自助收银程序。不说了,上烧烤代码。
1、定义一个收银策略抽象类,并且有一个抽象方法,参数为原价,返回优惠结算价。
public abstract class CashSuper {
public abstract double acceptCash(double money);
}
2、策略子类。
2-1)正常收费子类。
public class CashNormal extends CashSuper {
@Override
public double acceptCash(double money) {
return money;
}
}
2-2)满减策略类。
public class CashReturn extends CashSuper {
private double moneyConditation = 0.0; //满减条件
private double moneyReturn = 0.0; //减多少钱
public CashReturn(double moneyConditation, double moneyReturn) {
this.moneyConditation = moneyConditation;
this.moneyReturn = moneyReturn;
}
@Override
public double acceptCash(double money) {
double result = money;
if (money > moneyConditation){
result = money - Math.floor(money/moneyConditation) * moneyReturn;
}
return result;
}
}
2-3)打折策略类。
public class CashRebate extends CashSuper{
private double moneyRebate = 1; //折扣
public CashRebate(double moneyRebate){
this.moneyRebate = moneyRebate;
}
@Override
public double acceptCash(double money) {
return money * moneyRebate;
}
}
3、上下文类。声明一个CashSuper对象,通过构造方法,传入具体的收费策略,根据策略获得优惠结算价。
public class CashContext {
CashSuper cashSuper = null;
public CashContext(String type){
switch (type){
case "正常收费":
CashNormal cashNormal = new CashNormal();
cashSuper = cashNormal;
break;
case "满5减2":
CashReturn cashReturn = new CashReturn(5, 2);
cashSuper = cashReturn;
break;
case "打8折":
CashRebate cashRebate = new CashRebate(0.8);
cashSuper = cashRebate;
break;
}
}
public double getResult(double money){
return cashSuper.acceptCash(money);
}
}
4、客户端类。
public class CashCount {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
while (true){
System.out.println("-----------开始营业----------");
System.out.println("请输入促销策略:");
String type = scanner.next();
CashContext context = new CashContext(type);
System.out.println("客官,您要买多少钱烧烤呢");
double money = scanner.nextDouble();
double total = context.getResult(money);
System.out.println("优惠结算价:" + total);
System.out.println("-----------营业结束----------");
}
}
}
运行效果
小kim菌:😯满5减2比打8折划算耶!
小结:
1、策略模式和工厂模式区别
工厂模式是创建型模式 ,它关注对象创建,让对象的创建与具体的使用客户无关。策略模式是对象行为型模式 ,它定义了算法家族,分别封装起来,让它们之间可以切换,此模式让算法的变化,不会影响到使用算法的客户。
2、策略模式优缺点
优点:
1)定义的一系列算法完成的虽然都是相同的工作,只是实现过程不同,策略模式可以以相同的方式调用所有算法,减少了算法类与客户端类之间的耦合。
2)策略抽象类(文中的CashSuper)为Context定义了一系列可供重用的算法或行为,比如CashSuper的acceptCash,有助于析取出这些算法的公共功能。
3)策略模式遵循开闭原则,简化了单元测试,可灵活切换算法类,扩展只需增加算法类。
缺点:
1)策略算法类数量增多。
2)所有的策略都需要对外暴露,上层模块必须知道有哪些策略,然后才能知道采用哪种策略(悄悄透露:可以通过使用工厂模式、代理模式和享元模式修正,本文就是用了简单工厂模式把决策行为放到Context类,而不是放在客户端类)。
ps: 最近在学习设计模式,想通过记录故事的方式输出轻松易读的笔记。对自己是一种锻炼、成长,希望也能给学习编程的人儿带来一些些的帮助。希望自己能坚持。