策略模式(Strategy):Strategy是属于设计模式中 对象行为型模式,主要是定义一系列的算法,把这些算法一个个封装成单独的类.
再创建3个不同的模式来计算消费(继承现金收费类):
通过以上例子完成了策略模式的使用,重点是BaseCash抽象类和CashContext类。
改动后的测试代码如下:
通过简单工厂和策略两种模式的结合使用,把判断算法的工作也从客户端分离开了
,让他们之间可以互相替换,此模式让算法的变化不会影响到使用算法的客户
Strategy的结构图 :
下面用一个例子来说明策略模式(模拟商场的收费系统):
首先创建一个现金收费的抽象类
/**
*现金收费的抽象类,接收参数为商品原价
* @author thinkpad
*
*/
public abstract class BaseCash {
public abstract Double acceptCash(double money);
}
再创建3个不同的模式来计算消费(继承现金收费类):
/**
* 正常收费类,继承BaseCash
* @author thinkpad
*
*/
class Normal extends BaseCash {
@Override
public Double acceptCash(double money) {
return money;
}
}
/**
* 打折收费类,继承BaseCash
* @author thinkpad
*
*/
class Discount extends BaseCash {
private Double dis = 0D;
/*
* 利用构造方法初始化折扣
*/
public Discount(String dis) {
this.dis = Double.valueOf(dis);
}
@Override
public Double acceptCash(double money) {
return money*dis;
}
}
/**
* 返利收费类,继承BaseCash
* @author thinkpad
*
*/
class ReturnMoney extends BaseCash {
private double moneyCondition = 0d;
private double moneyReturn = 0d;
public ReturnMoney(double moneyCondition,double moneyReturn) {
this.moneyCondition = moneyCondition;
this.moneyReturn = moneyReturn;
}
@Override
public Double acceptCash(double money) {
double count = 0d;
if(money>=moneyCondition){
count = Math.floor(money/moneyCondition);
return money-moneyReturn*count;
}
return money;
}
创建一个CashContext类,用来维护对BaseCash对象的引用:
/**
* CashContext类,用来维护对BaseCash对象的引用
* @author thinkpad
*
*/
public class CashContext {
private BaseCash bc;
public CashContext(BaseCash baseCash) {
this.bc = baseCash;
}
/**
* 根据不同的收费对象计算实际金额
* @param money
* @return
*/
public double getResult(double money){
return bc.acceptCash(money);
}
}
建立一个测试类:
Scanner input = new Scanner(System.in);
CashContext cc = null;
String ans = null;
double totalPrice = 0d;
double total = 0d;
System.out.println("请选择优惠操作,1为正常收费;2为打8折;3为满300,返100");
int action = input.nextInt();
//根据选择的操作,将相应的策略对象传入CashContext的对象中
if(action==1){
cc = new CashContext( new Normal());
}else if(action==2){
cc = new CashContext(new Discount("0.8"));
}else if(action==3){
cc = new CashContext(new ReturnMoney(300,100));
}
do {
System.out.println("请输入单价");
Double price = input.nextDouble();
System.out.println("请输入数量");
int number = input.nextInt();
totalPrice = cc.getResult(price*number);//通过CashContext的getResult()的调用,可以得到收取费用的结果,让具体的算法与客户进行了隔离
total+=totalPrice;
System.out.println("是否继续添加商品Y/N");
ans = input.next();
} while (ans.equalsIgnoreCase("Y"));
System.out.println("付款金额为:"+total);
}
通过以上例子完成了策略模式的使用,重点是BaseCash抽象类和CashContext类。
以上只使用了策略模式完成功能,把判断算法的工作丢在了客户端,
下面我们简单工厂模式和策略模式结合起来完成上面的例子:
把CashContext类中代码改成下面所示:把之前的传入策略对象改成了传入判断策略的变量
/**
* CashContext类,用来维护对BaseCash对象的引用
* @author thinkpad
*
*/
public class CashContext {
private BaseCash bc;
public CashContext(int action) { //此时参数不是策略对象,而是一个表示收费类型的变量
if(action==1){
bc = new Normal(); //将实例化具体策略的过程由客户端转移到CashContext中,这是简单工厂的应用
}else if(action==2){
bc = new Discount("0.8");
}else if(action==3){
bc = new ReturnMoney(300,100);
}
}
/**
* 根据不同的收费对象计算实际金额
* @param money
* @return
*/
public double getResult(double money){
return bc.acceptCash(money);
}
}
改动后的测试代码如下:
Scanner input = new Scanner(System.in);
String ans = null;
double totalPrice = 0d;
double total = 0d;
System.out.println("请选择优惠操作,1为正常收费;2为打8折;3为满300,返100");
int action = input.nextInt();
CashContext cc = new CashContext(action);//此时参数不是策略对象,而是一个表示收费类型的变量
do {
System.out.println("请输入单价");
Double price = input.nextDouble();
System.out.println("请输入数量");
int number = input.nextInt();
totalPrice = cc.getResult(price*number);//通过CashContext的getResult()的调用,可以得到收取费用的结果,让具体的算法与客户进行了隔离
total+=totalPrice;
System.out.println("是否继续添加商品Y/N");
ans = input.next();
} while (ans.equalsIgnoreCase("Y"));
System.out.println("付款金额为:"+total);
}
通过简单工厂和策略两种模式的结合使用,把判断算法的工作也从客户端分离开了