您的位置:首页 > 其它

大话设计模式之策略模式(结合简单工厂),程序完善过程蕴含智慧

2015-12-13 14:11 489 查看
不管你编程经验多么丰富,也很难一次性写出完美无瑕的程序,程序都是一步步完善出来的,完善的过程中蕴含中无穷的智慧与乐趣,随着你编程的时间增加,你写的程序会一次比一次好,但是前提是你要不断的思考,随着面向对象语言的流行,我们要学会使用面向对象的思想来编写程序,而不是使用面向过程的方式来编写程序,但是这也需要不断锤炼,只要不断思考,我们终究可以写出完全面向对象的程序!废话有点多,请原谅,接下来说重点,说一下设计模式中的策略模式!请细心看完,你会有收获的!

1.设计一个商场商品收费软件,这是简化的,可能我们不会想太多,就马上着手编写程序。

package com.psc.construct.model.strategy;

import java.util.Scanner;

//商品收费
public class CashTest1 {

public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
System.out.print("请输入商品单价:");
String priceStr = sc.next(); //读出商品单价
System.out.print("请输入商品数量:");
String number = sc.next();  //读出商品数量
try {
double price = Double.valueOf(priceStr);
double num = Double.valueOf(number);
double totalPrice = price * num;
System.out.println("总价格为:" + totalPrice);
}catch(Exception e) {
e.printStackTrace();
}
}
}
2.写完这个程序的时候,我们心里就会有一种意犹未尽的感觉,不过也是,程序实在太简单,想一下,如果现在需要改变了,要求可以打折,此时我们之前编写的程序就要推到重新编写,这是一件很糟糕的thing。于是我们吸取教训,第二次完善一下程序。

package com.psc.construct.model.strategy;

import java.util.Scanner;

//商品收费(增加打折)
public class CashTest2 {

public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
System.out.print("请输入商品单价:");
String priceStr = sc.next(); //读出商品单价
System.out.print("请输入商品数量:");
String number = sc.next();  //读出商品数量
System.out.println("收费类型如下:");
String[] types = {"1-正常收费", "2-打八折", "3-打七折", "4-打五折"};
for (String temp : types) {
System.out.println(temp);
}
System.out.print("请选择收费类型的序号:");
String priceFlag = sc.next();
try {
double price = Double.valueOf(priceStr);
double num = Double.valueOf(number);
int flag = Integer.valueOf(priceFlag);
double totalPrice = 0.0;
switch(flag) {
case 1 : totalPrice = price * num; break;
case 2 : totalPrice = price * num * 0.8; break;
case 3 : totalPrice = price * num * 0.7; break;
case 4 : totalPrice = price * num * 0.5; break;
default : throw new RuntimeException("没有此收费类型序号!");
}
System.out.println("总价格为:" + totalPrice);
}catch(NumberFormatException e) {
e.printStackTrace();
}catch(Exception e) {
e.printStackTrace();
}
}
}


3.当我们写完这个程序的时候,依然有一种意犹未尽的感觉,因为一个主方法里面写了太多的代码,不利于控制和维护,看起来也乏力,如果此时需要又要改变的话,那就必须写该代码了,如是觉得要改善一下代码。

package com.psc.construct.model.strategy;

import java.util.Scanner;

//商品收费(增加打折--简单工厂)
public class CashTest3 {

public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
System.out.print("请输入商品单价:");
String priceStr = sc.next(); //读出商品单价
System.out.print("请输入商品数量:");
String number = sc.next();  //读出商品数量
System.out.println("收费类型如下:");
String[] types = {"1-正常收费", "2-打八折", "3-打七折", "4-打五折", "5-满300送100"};
for (String temp : types) {
System.out.println(temp);
}
System.out.print("请选择收费类型的序号:");
String priceFlag = sc.next();
try {
double price = Double.valueOf(priceStr);
double num = Double.valueOf(number);
int flag = Integer.valueOf(priceFlag);

CashSuper cashSuper = CashFactory.createPriceInstance(flag); //简单工厂

double totalPrice = cashSuper.acceptPrice(price * num);
System.out.println("总价格为:" + totalPrice);
}catch(NumberFormatException e) {
e.printStackTrace();
}catch(Exception e) {
e.printStackTrace();
}
}
}


package com.psc.construct.model.strategy;

public abstract class CashSuper {

public abstract double acceptPrice(double money);

}


package com.psc.construct.model.strategy;

//正常收费
public class CashNormal extends CashSuper {

@Override
public double acceptPrice(double money) {
return money;
}

}


package com.psc.construct.model.strategy;

//打折
public class CashRebate extends CashSuper {

private double rebate;

public CashRebate(double rebate) {
this.rebate = rebate;
}

@Override
public double acceptPrice(double money) {
return this.rebate * money;
}

}


package com.psc.construct.model.strategy;

//满300送100
public class CashReturn extends CashSuper {

private double fullPrice;

private double sendPrice;

public CashReturn(double fullPrice, double sendPrice) {
this.fullPrice = fullPrice;
this.sendPrice = sendPrice;
}

@Override
public double acceptPrice(double money) {
if (money >= fullPrice) {
return money - sendPrice;
}
return money;
}

}


package com.psc.construct.model.strategy;

public class CashFactory {

public static CashSuper createPriceInstance(int flag) {
CashSuper cashSuper;
switch(flag) {
case 1 : cashSuper = new CashNormal(); break;
case 2 : cashSuper = new CashRebate(0.8); break;
case 3 : cashSuper = new CashRebate(0.7); break;
case 4 : cashSuper = new CashRebate(0.5); break;
case 5 : cashSuper = new CashReturn(300, 100); break;
default : throw new RuntimeException("没有此收费类型");
}
return cashSuper;
}

}


4.我们想到了使用简单工厂来封装对象的创建细节,进而是的程序的拓展性提高,也利于维护,但是细心一想,需求可能随时改变,就算利于维护,维护的工作量也很大,需求改变了,每次都要修改工厂的类,从而满足需求,如是想到了策略模式。
package com.psc.construct.model.strategy;

import java.util.Scanner;

//商品收费(增加打折--策略模式)
public class CashTest4 {

public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
System.out.print("请输入商品单价:");
String priceStr = sc.next(); //读出商品单价
System.out.print("请输入商品数量:");
String number = sc.next();  //读出商品数量
System.out.println("收费类型如下:");
String[] types = {"1-正常收费", "2-打八折", "3-打七折", "4-打五折", "5-满300送100"};
for (String temp : types) {
System.out.println(temp);
}
System.out.print("请选择收费类型的序号:");
String priceFlag = sc.next();
try {
double price = Double.valueOf(priceStr);
double num = Double.valueOf(number);
int flag = Integer.valueOf(priceFlag);
CashContext cashContext; //收费的上下文
switch(flag) {
case 1 : cashContext = new CashContext(new CashNormal()); break;
case 2 : cashContext = new CashContext(new CashRebate(0.8)); break;
case 3 : cashContext = new CashContext(new CashRebate(0.7)); break;
case 4 : cashContext = new CashContext(new CashRebate(0.5)); break;
case 5 : cashContext = new CashContext(new CashReturn(300, 100)); break;
default : throw new RuntimeException("没有此收费类型序号!");
}
double totalPrice = cashContext.getFinalPrice(price) * num;
System.out.println("总价格为:" + totalPrice);
}catch(NumberFormatException e) {
e.printStackTrace();
}catch(Exception e) {
e.printStackTrace();
}
}
}


package com.psc.construct.model.strategy;

//定义一个上下文
public class CashContext {

private CashSuper cashSuper;

public CashContext(CashSuper cashSuper) {
this.cashSuper = cashSuper;
}

public double getFinalPrice(double money) {
//根据不同的收费策略取得不同的计算结果
return cashSuper.acceptPrice(money);
}
}


5.使用了策略模式,提供一个上下文,但是程序看起来不美观,如是结合简单工厂,晚上这个策略模式。

package com.psc.construct.model.strategy;

import java.util.Scanner;

//商品收费(增加打折--策略模式结合简单工厂)
public class CashTest5 {

public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
System.out.print("请输入商品单价:");
String priceStr = sc.next(); //读出商品单价
System.out.print("请输入商品数量:");
String number = sc.next();  //读出商品数量
System.out.println("收费类型如下:");
String[] types = {"1-正常收费", "2-打八折", "3-打七折", "4-打五折", "5-满300送100"};
for (String temp : types) {
System.out.println(temp);
}
System.out.print("请选择收费类型的序号:");
String priceFlag = sc.next();
try {
double price = Double.valueOf(priceStr);
double num = Double.valueOf(number);
int flag = Integer.valueOf(priceFlag);
//收费的上下文 使用简单工厂封装创建对象过程
CashContext cashContext = new CashContext(flag);
double totalPrice = cashContext.getFinalPrice(price * num);
System.out.println("总价格为:" + totalPrice);
}catch(NumberFormatException e) {
e.printStackTrace();
}catch(Exception e) {
e.printStackTrace();
}
}
}


package com.psc.construct.model.strategy;

//定义一个上下文
public class CashContext {

private CashSuper cashSuper;

//通过构造方法,传入具体的收费策略
public CashContext(int flag) {
//简单工厂
switch(flag) {
case 1 : cashSuper = new CashNormal(); break;
case 2 : cashSuper = new CashRebate(0.8); break;
case 3 : cashSuper = new CashRebate(0.7); break;
case 4 : cashSuper = new CashRebate(0.5); break;
case 5 : cashSuper = new CashReturn(300, 100); break;
default : throw new RuntimeException("没有此收费类型序号!");
}
}

public CashContext(CashSuper cashSuper) {
this.cashSuper = cashSuper;
}

public double getFinalPrice(double money) {
//根据不同的收费策略取得不同的计算结果
return cashSuper.acceptPrice(money);
}
}


6.简单工厂的使用,不一定都是创建一个工厂,也可以通过构造方法的方式实现,此时我们的程序的拓展性、可重用型、可维护性都可以得到提高,现在即使有需求的变更,也不用怕了,例如现在需求要求增加一个“满700减200”的活动需求,这时候我们只需要在CashContext类的构造方法中增加一个case条件,再在main方法中增加一个选项即可!
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: