背景
小李已经是一个工作一年的初级工程师了,他所在的公司是一家大型购物商场。随着各种网络购物软件兴起,老板也想做一个商场的购物 APP。分给小李的是一个一个订单结算模块,需要支持各种不同的结算策略。
需求
请帮小李写一个订单结算模块,要求支持多种结算策略:
- 原价
- 打 X 折
- 满减,满 X 元减 Y 元
请注意,商品有多种类型,每种类型可能会参与不同的活动,自然需要支持不同的结算策略。
任务
共三个小任务:
- Q1:方案设计。
- Q2:代码实现及结果截图。
- Q3:解释为什么要用这些模式。
要求
要求如下:
- 输入是一揽子商品,输出是最后的订单金额。
- 至少包含两种商品,每种使用不同的结算策略,策略可任选其中一个或两个组合(比如满减 + 打折)。
- 不要实现具体函数或方法的逻辑,可以使用
print
输出功能。
================================
类图
客户端:
import java.lang.reflect.Array;
import java.util.*;
public class Main {
public static void main(String[] args) {
double price = 0d;
double totalPrice = 0d;
double total = 0d;
int strategy = 0;
int num = 0;
Scanner scanner = new Scanner(System.in);
Integer goodCount=0;
Integer tag = 1;
String goods = "";
do{
System.out.println("---------------二、请输入商品销售模式 1.原价 2.八折 3.满300返100 4.先打8折,再满300返100 5. 先满200返50,再打7折 ---------------");
strategy = Integer.parseInt(scanner.nextLine());
System.out.println("---------------请输入商品单价:---------------");
price = Double.parseDouble(scanner.nextLine());
System.out.println("---------------请输入商品数量:---------------");
num = Integer.parseInt(scanner.nextLine());
System.out.println();
if(price >0 && num>0){
//这里就可以去写一个工厂
// CashSuper oper = CashFactory.createCrash(discount);
// totalPrice = oper.getCrash(price,num);
CashContext cc = new CashContext(strategy);
totalPrice = cc.getResult(price,num);
total = total + totalPrice;
System.out.println();
System.out.println("单价:" + price + "元 数量:" + num + " 合计:" + totalPrice + "元");
System.out.println();
System.out.println("总计:" + total + "元");
System.out.println();
}
goodCount++;
if(goodCount>=2){
System.out.println("是否退出?0-退出");
tag = Integer.parseInt(scanner.nextLine());
}
}while(goodCount<2 && tag>0);
System.out.println("感谢使用!");
}
}
CashContext:
public class CashContext {
private ISale cs;
public CashContext(int cashSuper){
// this.cs = cashSuper;
// CashSuper oper = null;
switch (cashSuper){
case 1:
this.cs = new CashNormal();
break;
case 2:
this.cs = new CashRebate(0.8d);
break;
case 3:
this.cs = new CashReturn(300d,100d);
case 4:
// 先打8折,再满300返100
CashNormal cn = new CashNormal();
CashReturn cr1 = new CashReturn(300d,100d);
CashRebate cr2 = new CashRebate(0.8d);
cr1.decorate(cn);
cr2.decorate(cr1);
this.cs = cr2;
break;
case 5:
//先满200返50,再打7折
CashNormal cn2 = new CashNormal();
CashRebate cr3 = new CashRebate(0.7d);
CashReturn cr4 = new CashReturn(200d,50d);
cr3.decorate(cn2); //用打7折算法包装基本的原价算法
cr4.decorate(cr3); //满200返50算法装饰打7折算法
this.cs = cr4; //将包装好的算法组合引用传递给cs对象
break;
}
}
public double getResult(double price,int num){
return this.cs.getCrash(price,num);
}
}
原价、打折、满减
public class CashNormal implements ISale {
public double getCrash(double price,int num){
return price * num;
}
}
public class CashRebate extends CashSuper {
private double moneyRebate = 1d;
public CashRebate(double moneyRebate){
this.moneyRebate = moneyRebate;
}
public double getCrash(double price,int num){
double result = price * num * this.moneyRebate;
return super.getCrash(result,1);
}
}
public class CashReturn extends CashSuper {
private double moneyReturn = 0d;
private double moneyCondition = 0d;
public CashReturn(double moneyCondition,double moneyReturn){
this.moneyReturn = moneyReturn;
this.moneyCondition = moneyCondition;
}
public double getCrash(double price,int num){
double result = price * num;
if (moneyCondition>0 && result >= moneyCondition){
result = result - Math.floor(result/moneyCondition) * moneyReturn;
}
return super.getCrash(result,1);
}
}
定义装饰方法
public class CashSuper implements ISale{
protected ISale component;
public void decorate(ISale component){
this.component = component;
}
public double getCrash(double price,int num){
double result = 0d;
if(this.component != null){
result = this.component.getCrash(price,num);
}
return result;
}
}
接口
public interface ISale {
public double getCrash(double price,int num);
}
为什么要用这些模式?
我的理解是简单工厂模式首先把业务逻辑抽离出来,主要是跟客户端的业务逻辑分离。
策略模式:仅仅比工厂模式多一个类,去选择使用哪一个模式。
装饰模式:它把每个要装饰的功能放在单独的类中,并让这个类包装它所要装饰的对象,因此,当需要执行特殊行为时,客户代码就可以在运行时根据需要有选择地、按顺序地使用装饰功能包装对象了.