public class Program {
public static void main(String[] args) {
Scanner sc=new Scanner(System.in);
System.out.println("單價:");
String numberOne = sc.next();
System.out.println("數量:");
String numberTwo = sc.next();
System.out.println("打折率:");
String rang = sc.next();
if(!StringUtils.isNumeric(rang)){
System.out.println("打折率輸入錯誤");
System.exit(0);
}
// 獲取實際打折率
float[] rangArr = new float[]{0,0.9f,0.8f,0.7f};
float total = 0f;
String rangStr = "不打折";
try {
switch (Integer.parseInt(rang)) {
case 0 :
total = Float.parseFloat(numberOne) * Float.parseFloat(numberTwo);
rangStr = "不打折";
break;
case 9 :
total = Float.parseFloat(numberOne) * Float.parseFloat(numberTwo) * rangArr[10 - Integer.parseInt(rang)];
rangStr = "打9折";
break;
case 8 :
total = Float.parseFloat(numberOne) * Float.parseFloat(numberTwo) * rangArr[10 - Integer.parseInt(rang)];
rangStr = "打8折";
break;
case 7 :
total = Float.parseFloat(numberOne) * Float.parseFloat(numberTwo) * rangArr[10 - Integer.parseInt(rang)];
rangStr = "打7折";
break;
default:
throw new RuntimeException("不包含此種折扣");
}
} catch (Exception e) {
e.printStackTrace();
System.out.println("輸入的單價或者數量不是正數或者不包含此種折扣");
System.exit(0);
}
System.out.println("總計:" + rangStr + "後 " + total);
}
}
問題來了:“這樣子增加一個算法,就更改一下代碼,又不利於其他算法的保密,也不符合面向對象的三大特性”。我:想起了上次的優化,使用簡單工廠設計模式改進一次。
public class Program {
public static void main(String[] args) {
Scanner sc=new Scanner(System.in);
System.out.println("單價:");
String price = sc.next();
System.out.println("數量:");
String number = sc.next();
System.out.println("打折率:");
String rang = sc.next();
// 獲取實際打折率
double[] rangArr = new double[]{0,0.9f,0.8f,0.7f};
double total = 0f;
try {
CashSuper cash = CashFactory.createCash(rang);
total = cash.acceptCash(Double.parseDouble(price) * Double.parseDouble(number)) ;
} catch (Exception e) {
e.printStackTrace();
System.out.println("輸入的單價或者數量不是正數或者不包含此種折扣");
System.exit(0);
}
System.out.println("總計:" + rang + "後 " + total);
}
}
abstract class CashSuper{
public abstract double acceptCash(double money);
}
// 正常收費
class CashNormal extends CashSuper{
@Override
public double acceptCash(double money) {
return money;
}
}
// 打折收費
class CashRebate extends CashSuper{
private double moneyRebate = 1l;
public CashRebate(double moneyRebate) {
this.moneyRebate = moneyRebate;
}
@Override
public double acceptCash(double money) {
return money * moneyRebate;
}
}
// 滿多少返利
class CashReturn extends CashSuper{
private double moneyCondition = 0.0f;
private double moneyReturn = 0.0f;
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;
}
}
class CashFactory {
public static CashSuper createCash(String rang) {
CashSuper cash = null;
switch (rang) {
case "不打折":
cash = new CashNormal();
break;
case "打9折":
cash = new CashRebate(0.9f);
break;
case "打8折":
cash =new CashRebate(0.8f);
break;
case "滿300送100":
cash = new CashReturn(300,100);
break;
default:
throw new RuntimeException("不包含此種折扣");
}
return cash;
}
}
問題來了:“上面每增加一個算法都要更改工廠模式,重複利用代碼少了,有沒有更好的的設計模式呢”,最終找到了策略設計模式public class Program {
public static void main(String[] args) {
Scanner sc=new Scanner(System.in);
System.out.println("單價:");
String price = sc.next();
System.out.println("數量:");
String number = sc.next();
System.out.println("打折率:");
String rang = sc.next();
// 獲取實際打折率
double[] rangArr = new double[]{0,0.9f,0.8f,0.7f};
double total = 0f;
CashContext cash = null;
try {
switch (rang) {
case "不打折":
cash = new CashContext(new CashNormal());
break;
case "打9折":
cash = new CashContext(new CashRebate(0.9f));
break;
case "打8折":
cash = new CashContext(new CashRebate(0.8f));
break;
case "滿300送100":
cash = new CashContext(new CashReturn(300, 100));
break;
default:
throw new RuntimeException("不包含此種折扣");
}
total = cash.getResult(Double.parseDouble(price) * Double.parseDouble(number)) ;
} catch (Exception e) {
e.printStackTrace();
System.out.println("輸入的單價或者數量不是正數或者不包含此種折扣");
System.exit(0);
}
System.out.println("總計:" + rang + "後 " + total);
}
}
abstract class CashSuper{
public abstract double acceptCash(double money);
}
// 正常收費
class CashNormal extends CashSuper{
@Override
public double acceptCash(double money) {
return money;
}
}
// 打折收費
class CashRebate extends CashSuper{
private double moneyRebate = 1l;
public CashRebate(double moneyRebate) {
this.moneyRebate = moneyRebate;
}
@Override
public double acceptCash(double money) {
return money * moneyRebate;
}
}
// 滿多少返利
class CashReturn extends CashSuper{
private double moneyCondition = 0.0f;
private double moneyReturn = 0.0f;
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;
}
}
class CashContext{
private CashSuper strage;
public CashContext(CashSuper strage) {
this.strage = strage;
}
public double getResult(double money){
return strage.acceptCash(money);
}
}
仔細看了,這不是又回到了起點,還多封裝了一次。重複代碼更多了。又改如何改進?策略與簡單工廠模式的結合
public class Program {
public static void main(String[] args) {
Scanner sc=new Scanner(System.in);
System.out.println("單價:");
String price = sc.next();
System.out.println("數量:");
String number = sc.next();
System.out.println("打折率:");
String rang = sc.next();
// 獲取實際打折率
double[] rangArr = new double[]{0,0.9f,0.8f,0.7f};
double total = 0f;
try {
CashContext cash = new CashContext(rang);
total = cash.getResult(Double.parseDouble(price) * Double.parseDouble(number)) ;
} catch (Exception e) {
e.printStackTrace();
System.out.println("輸入的單價或者數量不是正數或者不包含此種折扣");
System.exit(0);
}
System.out.println("總計:" + rang + "後 " + total);
}
}
abstract class CashSuper{
public abstract double acceptCash(double money);
}
// 正常收費
class CashNormal extends CashSuper{
@Override
public double acceptCash(double money) {
return money;
}
}
// 打折收費
class CashRebate extends CashSuper{
private double moneyRebate = 1l;
public CashRebate(double moneyRebate) {
this.moneyRebate = moneyRebate;
}
@Override
public double acceptCash(double money) {
return money * moneyRebate;
}
}
// 滿多少返利
class CashReturn extends CashSuper{
private double moneyCondition = 0.0f;
private double moneyReturn = 0.0f;
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;
}
}
class CashContext{
private CashSuper strage;
public CashContext(String rang) {
switch (rang) {
case "不打折":
strage = new CashNormal();
break;
case "打9折":
strage = new CashRebate(0.9f);
break;
case "打8折":
strage = new CashRebate(0.8f);
break;
case "滿300送100":
strage = new CashReturn(300, 100);
break;
default:
throw new RuntimeException("不包含此種折扣");
}
}
public double getResult(double money){
return strage.acceptCash(money);
}
}
簡單工廠模式和策略簡單工廠模式的比較簡單工廠模式
CashSuper cash = CashFactory.createCash(rang);
total = cash.acceptCash(Double.parseDouble(price) * Double.parseDouble(number)) ;
策略工廠模式CashContext cash = new CashContext(rang);
total = cash.getResult(Double.parseDouble(price) * Double.parseDouble(number)) ;
簡單工廠模式調用者需要認識兩個類,CashSuper和CashFactory,而策略工廠模式只要認識CashContext一個類。耦合程度更加降低最後的反思:感覺策略模式用處並不是很大,只不過封裝了一次,讓調用者與算法分離。降低耦合度,但是代碼量增多了,閱讀複雜。更多等以後理解更深刻了,再補充。