说明:在商店计算商品,原来只是计算商品单价和数量,后来又增加了打折,满减等等优惠活动,对于这种不断出现新方案,可以使用策略模式。
作用:根据不同类型做出相应的抉择,类似诸葛亮的锦郎妙计。从概念上来看,这些算法完成的都是相同的工作,只是实现不同。
1、简单工厂模式实现
1、下面定义的抽象方法
public abstract class CashSuper {
public abstract double acceptCash(double price,int num);
}
2、下面的是对抽象类进行实现
public class CashNormal extends CashSuper {
//正常收费,原价返回
public double acceptCash(double price,int num){
return price * num;
}
}
public class CashRebate extends CashSuper {
private double moneyRebate = 1d;
//打折收费。初始化时必需输入折扣率。八折就输入0.8
public CashRebate(double moneyRebate){
this.moneyRebate = moneyRebate;
}
//计算收费时需要在原价基础上乘以折扣率
public double acceptCash(double price,int num){
return price * num * this.moneyRebate;
}
}
public class CashReturn extends CashSuper {
private double moneyCondition = 0d; //返利条件
private double moneyReturn = 0d; //返利值
//返利收费。初始化时需要输入返利条件和返利值。
//比如“满300返100”,就是moneyCondition=300,moneyReturn=100
public CashReturn(double moneyCondition,double moneyReturn){
this.moneyCondition = moneyCondition;
this.moneyReturn = moneyReturn;
}
//计算收费时,当达到返利条件,就原价减去返利值
public double acceptCash(double price,int num){
double result = price * num;
if (moneyCondition>0 && result >= moneyCondition)
result = result - Math.floor(result / moneyCondition) * moneyReturn;
return result;
}
}
3、下面的是简单工厂的核心
public class CashFactory {
//收费工厂
public static CashSuper createCashAccept(int cashType){
CashSuper cs = null;
switch (cashType) {
case 1:
cs = new CashNormal(); //正常收费
break;
case 2:
cs = new CashRebate(0.8d); //打八折
break;
case 3:
cs = new CashRebate(0.7d); //打七折
break;
case 4:
cs = new CashReturn(300d,100d);//满300返100
break;
}
return cs;
}
}
4、测试和运行结果
public class Test {
public static void main(String[] args){
System.out.println("**********************************************");
System.out.println("《大话设计模式》代码样例");
System.out.println();
int discount = 0; //商品折扣模式(1.正常收费 2.打八折 3.打七折)
double price = 0d; //商品单价
int num = 0; //商品购买数量
double totalPrices = 0d;//当前商品合计费用
double total = 0d; //总计所有商品费用
Scanner sc = new Scanner(System.in);
do {
System.out.println("请输入商品折扣模式(1.正常收费 2.打八折 3.打七折 4.满300送100):");
discount = Integer.parseInt(sc.nextLine());
System.out.println("请输入商品单价:");
price = Double.parseDouble(sc.nextLine());
System.out.println("请输入商品数量:");
num = Integer.parseInt(sc.nextLine());
System.out.println();
if (price>0 && num>0){
//简单工厂模式根据discount的数字选择合适的收费类生成实例
CashSuper csuper = CashFactory.createCashAccept(discount);
//通过多态,可以根据不同收费策略计算得到收费的结果
totalPrices = csuper.acceptCash(price,num);
total = total + totalPrices;
System.out.println();
System.out.println("单价:"+ price + "元 数量:"+ num +" 合计:"+ totalPrices +"元");
System.out.println();
System.out.println("总计:"+ total+"元");
System.out.println();
}
}
while(price>0 && num>0);
System.out.println();
System.out.println("**********************************************");
}
}
运行结果
2.策略模式实现
1、定义抽象类型
public abstract class CashSuper {
public abstract double acceptCash(double price,int num);
}
2、对抽象类进行实现
public class CashNormal extends CashSuper {
//正常收费,原价返回
public double acceptCash(double price,int num){
return price * num;
}
}
public class CashRebate extends CashSuper {
private double moneyRebate = 1d;
//打折收费。初始化时必需输入折扣率。八折就输入0.8
public CashRebate(double moneyRebate){
this.moneyRebate = moneyRebate;
}
//计算收费时需要在原价基础上乘以折扣率
public double acceptCash(double price,int num){
return price * num * this.moneyRebate;
}
}
public class CashReturn extends CashSuper {
private double moneyCondition = 0d; //返利条件
private double moneyReturn = 0d; //返利值
//返利收费。初始化时需要输入返利条件和返利值。
//比如“满300返100”,就是moneyCondition=300,moneyReturn=100
public CashReturn(double moneyCondition,double moneyReturn){
this.moneyCondition = moneyCondition;
this.moneyReturn = moneyReturn;
}
//计算收费时,当达到返利条件,就原价减去返利值
public double acceptCash(double price,int num){
double result = price * num;
if (moneyCondition>0 && result >= moneyCondition)
result = result - Math.floor(result / moneyCondition) * moneyReturn;
return result;
}
}
3、核心代码(重点)
对上面抽象类进行分装,通过多态的方式,传递不同的实现类,间接的调用不同的对象
public class CashContext {
private CashSuper cs; //声明一个CashSuper对象
//通过构造方法,传入具体的收费策略
public CashContext(CashSuper csuper){
this.cs = csuper;
}
public double getResult(double price,int num){
//根据收费策略的不同,获得计算结果
return this.cs.acceptCash(price,num);
}
}
4、核心调用
关键部分截图
下面的是完整的代码
public class Test {
public static void main(String[] args){
System.out.println("**********************************************");
System.out.println("《大话设计模式》代码样例");
System.out.println();
int discount = 0; //商品折扣模式(1.正常收费 2.打八折 3.打七折)
double price = 0d; //商品单价
int num = 0; //商品购买数量
double totalPrices = 0d;//当前商品合计费用
double total = 0d; //总计所有商品费用
Scanner sc = new Scanner(System.in);
do {
System.out.println("请输入商品折扣模式(1.正常收费 2.打八折 3.打七折 4.满300送100):");
discount = Integer.parseInt(sc.nextLine());
System.out.println("请输入商品单价:");
price = Double.parseDouble(sc.nextLine());
System.out.println("请输入商品数量:");
num = Integer.parseInt(sc.nextLine());
System.out.println();
if (price>0 && num>0){
CashContext cc = null;
//根据用户输入,将对应的策略对象作为参数传入CashContent对象中
switch(discount){
case 1:
cc = new CashContext(new CashNormal());
break;
case 2:
cc = new CashContext(new CashRebate(0.8d));
break;
case 3:
cc = new CashContext(new CashRebate(0.7d));
break;
case 4:
cc = new CashContext(new CashReturn(300d,100d));
break;
}
//通过Context的getResult方法的调用,可以得到收取费用的结果
//让具体算法与客户进行了隔离
totalPrices = cc.getResult(price,num);
total = total + totalPrices;
System.out.println();
System.out.println("单价:"+ price + "元 数量:"+ num +" 合计:"+ totalPrices +"元");
System.out.println();
System.out.println("总计:"+ total+"元");
System.out.println();
}
}
while(price>0 && num>0);
System.out.println();
System.out.println("**********************************************");
}
}
3、简单工厂模式和策略模式结合
由于代码很多类似的,对于抽象类和相应的实现就不写了,其他的代码不变
1、添加了简单工厂
下面的这块的代码用到简单工厂
public class CashContext {
private CashSuper cs; //声明一个CashSuper对象
//通过构造方法,传入具体的收费策略
public CashContext(int cashType){
switch(cashType){
case 1:
this.cs = new CashNormal();
break;
case 2:
this.cs = new CashRebate(0.8d);
break;
case 3:
this.cs = new CashRebate(0.7d);
break;
case 4:
this.cs = new CashReturn(300d,100d);
break;
}
}
public double getResult(double price,int num){
//根据收费策略的不同,获得计算结果
return this.cs.acceptCash(price,num);
}
}
2、测试结果
public class Test {
public static void main(String[] args){
System.out.println("**********************************************");
System.out.println("《大话设计模式》代码样例");
System.out.println();
int discount = 0; //商品折扣模式(1.正常收费 2.打八折 3.打七折)
double price = 0d; //商品单价
int num = 0; //商品购买数量
double totalPrices = 0d;//当前商品合计费用
double total = 0d; //总计所有商品费用
Scanner sc = new Scanner(System.in);
do {
System.out.println("请输入商品折扣模式(1.正常收费 2.打八折 3.打七折 4.满300送100):");
discount = Integer.parseInt(sc.nextLine());
System.out.println("请输入商品单价:");
price = Double.parseDouble(sc.nextLine());
System.out.println("请输入商品数量:");
num = Integer.parseInt(sc.nextLine());
System.out.println();
if (price>0 && num>0){
//根据用户输入,将对应的策略对象作为参数传入CashContext对象中
CashContext cc = new CashContext(discount);
//通过Context的getResult方法的调用,可以得到收取费用的结果
//让具体算法与客户进行了隔离
totalPrices = cc.getResult(price,num);
total = total + totalPrices;
System.out.println();
System.out.println("单价:"+ price + "元 数量:"+ num +" 合计:"+ totalPrices +"元");
System.out.println();
System.out.println("总计:"+ total+"元");
System.out.println();
}
}
while(price>0 && num>0);
System.out.println();
System.out.println("**********************************************");
}
}