它定义了算法家族.分别封装起来让他们可以互相替换.这个模式让算法的变化不会影响到使用算法的用户
策略模式是一种定义一系列的方法,从概念上来看,所有这些算法完成的都是相同的工作,只是实现不停,简单来说策略模式就是来封装算法的,但是在实践过程中,我们发现可以使用它封装所有类的规则,只要在分析过程中听到需要在不同时间应用不同的业务规则,就可以考虑使用策略模式处理多变的可能性
优点:
- 简化测试单元,因为每一个算法都有自己的类,可以通过自己的接口单独测试
- 与简单工厂对比,只需要让客户端认识一个类(CashSuperContext.class)而简单工厂需要然后端了解具体算法对象的父类(CashSuper.class)与工厂类(CashFactory),相对而言耦合度降低
但对下面的代码而言,策略模式的缺点在于CashContext上下文中,如果需求多变的情况也是需要成本的,但是成本也是有高低的,高手与菜鸟的差距,高手可以用同样的代价获取最大的收益,或者同样的事情花最小的代价,**(书中说的…)可以使用抽象工厂进行简化,抽象工厂在后面会补充
商场促销
- 一下代码在抽象父类(CashSuper.class)中创建抽象方法(acceptCash),也可以说父类为抽象策略
- 所有子类继承父类,重写抽象方法(acceptCash),子类换言而之就是具体算法
- 在上下文(CashSuperContext.class)中,对具体算法进行分配
- 客户端只需要调用上下文(CashSuperContext.class)就可以对算法进行使用
CashSuper.class(收费父类)
public abstract class CashSuper {
/**
* 现金收取超类的抽象方法,收取现金
* @param money 原价金额
* @return 返回为当前价格
*/
public abstract double acceptCash(double money);
}
CashRebate.class(打折子类)
/**
* 打折子类
*/
public class CashRebate extends CashSuper {
private double moneyRebate = 0;
/**
* 初始化时必须输入打折率,0.8就是八折
* @param moneyRebate
*/
public CashRebate(double moneyRebate) {
this.moneyRebate = moneyRebate;
}
/**
* 现金收取超类的抽象方法,收取现金
*
* @param money 原价金额
* @return 返回为当前价格
*/
@Override
public double acceptCash(double money) {
return money * moneyRebate;
}
}
CashReturn.class(满减子类)
/**
* 返利收费子类
*/
public class CashReturn extends CashSuper {
private double moneyReturn;
private double moneyCondition;
/**
* 初始化时必须输入返利数据
*
* @param moneyReturn
* @param moneyCondition
*/
public CashReturn(double moneyReturn, double moneyCondition) {
this.moneyReturn = moneyReturn;
this.moneyCondition = moneyCondition;
}
/**
* 现金收取超类的抽象方法,收取现金
*
* @param money 原价金额
* @return 满足返利条件进行返利,不满足返回原金额
*/
@Override
public double acceptCash(double money) {
if (money >= this.moneyReturn) { //满足返利条件
money -= moneyCondition;
}
return money;
}
}
CashNormal.class(正常收费子类)
/**
* 正常收费子类
*/
public class CashNormal extends CashSuper{
/**
* 正常收费类,没有任何优惠
* @param money 原价金额
* @return 返回原价金额
*/
@Override
public double acceptCash(double money) {
return money;
}
}
CashSuperContext.class(策略模式上下文)
/**
* 根据策略模式修改简单工厂类
*/
public class CashSuperContext {
private CashSuper sc;
private double money;
public CashSuperContext(CashSuper sc) {
this.sc = sc;
}
public CashSuperContext(double money) {
this.money = money;
}
public double getResult(double money) {
return sc.acceptCash(money);
}
public double getReult(Integer type) {
CashSuper sc = null;
switch (type) {
case 1:
sc = new CashReturn(300, 100);
break;
case 2:
sc = new CashRebate(0.95);
break;
default:
sc = new CashNormal();
break;
}
return sc.acceptCash(money);
}
}
btnOk_Click.class(计算机确认按钮)
/**
* 策略模式
*/
public class btnOk_Click {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
boolean isTrue = true;
double sum = 0; //合计
while (isTrue) {
System.out.println("请输入商品金额");
String jine = sc.nextLine();
double jines = 0.0;
try {
jines = Double.valueOf(jine);
} catch (Exception e) {
System.out.println("非法金额数值!");
isTrue = false;
}
System.out.println("请输入商品数量:");
String numbers = sc.nextLine();
if (numbers.matches("[0-9]*")) { //验证数量是否为正常数字
sum += Integer.valueOf(numbers) * jines;
} else {
System.out.println("输入数量非法!!");
isTrue = false;
}
System.out.println("当前合计金额=" + sum);
System.out.println("结束(1) 重置(2) 继续(3)");
String btns = sc.nextLine();
if (btns.equals("1")) {
//使用简单工厂模式
// System.out.println("当前优惠服务有(1.满减,2.打折,3.无优惠):");
// int type = Integer.valueOf(sc.nextLine());
// CashSuper cashAccept = CashFactory.createCashAccept(type == 1 ? "满减" : type == 2 ? "打折" : "正常收费");
// double v = cashAccept.acceptCash(sum);
// System.out.println("最后消费金额:"+v);
//使用策略模式
// System.out.println("当前优惠服务有(1.满减,2.打折,3.无优惠):");
// int type = Integer.valueOf(sc.nextLine());
// CashSuperContext csc = null;
// switch (type) {
// case 1:
// csc = new CashSuperContext(new CashReturn(300,100));
// break;
// case 2:
// csc = new CashSuperContext(new CashRebate(0.95));
// break;
// default:
// csc = new CashSuperContext(new CashNormal());
// break;
// }
// System.out.println("最后消费金额:"+csc.getResult(sum));
//使用策略模式与工厂模式结合
System.out.println("当前优惠服务有(1.满减,2.打折,3.无优惠):");
int type = Integer.valueOf(sc.nextLine());
CashSuperContext csc = new CashSuperContext(sum);
System.out.println("最后消费金额:"+ csc.getReult(type));
isTrue = false;
} else if (btns.equals("2")) {
sum = 0; //金额重置
System.out.println("金额已重置当前金额为= " + sum);
}
}
}
}