目录
策略模式
本质:分离算法,选择实现。
使用策略模式可以把行为和环境分割开来。环境类负责维持和查询行为类,各种算法则在具体策略类(ConcreteStrategy)中提供。
当出现新的促销折扣或现有的折扣政策出现变化时,只需要实现新的策略类,并在客户端登记即可。
环境(Context)角色:有一个Strategy类的引用,负责和具体的策略类交互。
抽象策略(Strategy)角色:通常由一个接口或抽象类实现,给出所有的具体策略类所需的接口。
具体策略(ConcreteStrategy)角色:包装了相关的算法或行为。
在策略模式中,通常是上下文使用具体的策略实现对象,反过来,策略实现对象也可以从上下文获取所需要的数据,因此可以将上下文当参数传递给策略实现对象在这种情况下,上下文封装着具体策略对象进行算法运算所需要的数据,具体策略对象通过回调上下文的方法来获取这些数据。
策略模式的收银软件
定义抽象类CashStrategy:定义收银的计算方法
定义CashContext角色:引用CashStrategy的一个对象
CashNormal是正常收费,CashRebate是打折收费,CashReturn是返利收费,是三个具体策略,具体选择使用哪一个算法功能放到客户端判断。
public abstract class CashStrategy {
public abstract double acceptCash(double money);
}
public class CashContext {
private CashStrategy cs;
public CashContext(CashStrategy cs) {
this.cs = cs;
}
public double getResult(double money) {
return cs.acceptCash(money);
}
}
public class CashNormal extends CashStrategy{
@Override
public double acceptCash(double money) {
// TODO Auto-generated method stub
return money;
}
}
public class CashRebate extends CashStrategy{
private double moneyRebate=0;
public CashRebate(double moneyRebate) {
this.moneyRebate = moneyRebate;
}
@Override
public double acceptCash(double money) {
return money*moneyRebate;
}
}
public class CashRetrun extends CashStrategy{
private double moneyCondition=0.0;
private double moneyReturn=0.0;
public CashRetrun(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;
//floor():向下取整
return result;
}
}
import java.util.Scanner;
public class Test {
static double total=0.0;
public static void main(String[] args) {
Scanner cin=new Scanner(System.in);
System.out.println("请输入优惠方案:");
String str=cin.next();
CashContext cc=null;
switch(str) {
case "正常收费":
cc=new CashContext(new CashNormal());
break;
case "满300返100":
cc=new CashContext(new CashRetrun(300,100));
break;
case "打8折":
cc=new CashContext(new CashRebate(0.8));
break;
}
System.out.println("请输入消费金额:");
double price=cin.nextInt();
total=cc.getResult(price);
System.out.println("最后共消费:"+total);
cin.close();
}
}
策略模式的特点
- 功能:具体算法从具体业务处理中独立
- 多个if-else出现考虑使用策略模式
- 策略算法是形同行为的不同实现(多态)
- 客户端选择,由上下文来具体实现策略算法
使用场景
出现同一个算法,有很多不同的实现的情况,可以使用策略模式来把这些“不同的实现”实现成为一个算法的类层次。
出现抽象一个定义了很多行为的类,并且是通过多个if-else语句来选择这些行为的情况,可以使用策略模式来代替这些条件语句。
优缺点
优点:
- 避免让客户端涉及到重要算法和数据
- 避免使用难以维护的多重条件选择语句
- 更好的扩展
缺点:
- 判断逻辑在客户端,想按需改变算法时,还是要去更改客户端的程序。
- 客户端必须知道所有的策略类,并自行决定使用哪一个策略类。这就意味着客户端必须理解这些算法的区别,以便适时选择恰当的算法类。
- 增加了对象的数目
- 只适合扁平的算法结构
策略模式和工厂模式的结合
把分支判断放到到环境角色(CashContext类)中,其它类不做改变
public class CashContext {
private CashStrategy cs=null;
//简单工厂:将实例化具体策略从客户端放入Context类中
public CashContext(String type) {
switch(type) {
case "正常收费":
CashNormal cs0=new CashNormal();
cs=cs0;
break;
case "满300返100":
CashRetrun cr1=new CashRetrun(300,100);
cs=cr1;
break;
case "打8折":
CashRebate cr2=new CashRebate(0.8);
cs=cr2;
break;
}
}
public double getResult(double money) {
return cs.acceptCash(money);
}
}
import java.util.Scanner;
public class Test {
public static void main(String[] args) {
Scanner cin=new Scanner(System.in);
System.out.println("请输入优惠方案:");
String str=cin.next();
CashContext cc=new CashContext(str);
System.out.println("请输入消费金额:");
double price=cin.nextInt();
double total=cc.getResult(price);
System.out.println("最终消费:"+total);
cin.close();
}
}