一、概念
策略模式:它定义了算法家族,分别封装起来,让它们之间可以互相替换,此模式让算法的变化,不会影响到使用算法的客户。
二、使用示例
现在有一个需求,做一个商场打折计算器,根据客户所购买的单价和数量,进行结算。
我们把打折活动看成是商场的活动策略
public abstract class Strategy {
public abstract void algorithm();
}
打八折看成策略A
//具体算法A
public class ChildStrategyA extends Strategy {
@Override
public void algorithm() {
//算法A实现方法
System.out.print("算法A计算");
Log.i("test","算法A计算");
}
}
满300减100看成策略B
//具体算法B
public class ChildStrategyB extends Strategy {
@Override
public void algorithm() {
//算法A实现方法
System.out.print("算法B计算");
Log.i("test","算法B计算");
}
}
正常收费
//具体算法C
public class ChildStrategyC extends Strategy {
@Override
public void algorithm() {
//算法A实现方法
Log.i("test","算法C计算");
}
}
收费计算类
public class Cashier {
Strategy strategy;
public Cashier(Strategy strategy) {
this.strategy = strategy;
}
public void account(){
strategy.algorithm();
}
}
三种活动收费,调用代码
val cashier1 = Cashier(ChildStrategyA())
val cashier2 = Cashier(ChildStrategyB())
val cashier3 = Cashier(ChildStrategyC())
cashier1.account()
cashier2.account()
cashier3.account()
由于实例化不同的策略,所以最终在调用account()方法时,所获得的结果就不尽相同。结果:
算法A计算
算法B计算
算法C计算
虽然达到了我们想要的结果,但是还不是真正意义上的策略。其实,以真实商场活动环境,正常收费是一种策略,打折收费是一种策略,返利收费又是一种策略,也就是策略模式中说的具体算法。
现在我们根据上面三种策略,改写一下上面的代码:
//此处用了策略模式和简单工厂模式结合,如果只用简单工厂模式,我们就会有一个CashFactory.createCashType(String type)返回一个CashSuper。由于只使用简单工厂模式,需要知道两个类CashFactory和CashSuper所以,我们这里为了更好的封装细节,采用策略模式和简单工厂模式结合,对外只暴露CashContext一个类就可以了。
public class CashContext {
CashSuper cashSuper = null;
public CashContext(String type) {
switch (type) {
case "正常收费":
CashNormal cashNormal = new CashNormal();
cashSuper = cashNormal;
break;
case "满300 返 100":
CashReturn cashReturn = new CashReturn("300", "100");
cashSuper = cashReturn;
break;
case "8折":
CashRebate cashRebate = new CashRebate("0.8");
cashSuper = cashRebate;
break;
}
}
public double getResult(double money) {
return cashSuper.acceptCash(money);
}
}
//正常现金收费类
public class CashNormal extends CashSuper {
@Override
public double acceptCash(double money) {
return money;
}
}
//打折收费类
public class CashRebate extends CashSuper {
private double moneyRebate = 1d;
public CashRebate(String moneyRebate) {
this.moneyRebate = Double.parseDouble(moneyRebate);
}
@Override
public double acceptCash(double money) {
return money * moneyRebate;
}
}
//打折收费类
public class CashRebate extends CashSuper {
private double moneyRebate = 1d;
public CashRebate(String moneyRebate) {
this.moneyRebate = Double.parseDouble(moneyRebate);
}
@Override
public double acceptCash(double money) {
return money * moneyRebate;
}
}
调用代码
Double total = 0d;
CashContext cashContext = CashContext("8折");
//买了四件单价100元的秋裤
total += cashContext.getResult((100 * 4).toDouble());
测试结果:
total cost : 320.0