策略模式
定义
策略模式定义了一系列的算法,并将每一个算法封装起来,使每个算法可以相互替代,使算法本身和使用算法的客户端分割开来,相互独立。
结构
-
策略接口角色 IStrategy: 用来约束一系列具体的策略算法,策略上下文角色 ConcreteStrategy 使用此策略接口来调用具体的策略所实现的算法。
-
具体策略实现角色 ConcreteStrategy: 具体的策略实现,即具体的算法实现。
-
策略上下文角色 StrategyContext: 策略上下文,负责和具体的策略实现交互,通常策略上下文对象会持有一个真正的策略实现对象,策略上下文还可以让具体的策略实现从其中获取相关数据,回调策略上下文对象的方法。
UML 类图:
UML 序列图:
现在需求是收银,根据不同的类型采取相应的收银策略(返现,折扣)
原始写法
@Slf4j
public class market {
private BigDecimal total = new BigDecimal("0.0");
private void calculateTotalPrice(BigDecimal goodsPrice, BigDecimal goodsNum, String discount) {
BigDecimal totalPrice = goodsPrice.multiply(goodsNum);
// 打折
total = discountPrice(totalPrice, discount);
log.info("===============================");
log.info("单价:" + goodsPrice + " 数量:" + goodsNum + " 合计:" + total);
log.info("===============================");
}
/**
* 打折后的价格
*
* @param totalPrice
* @param discount
* @return BigDecimal total
*/
private BigDecimal discountPrice(BigDecimal totalPrice, String discount) {
totalPrice = totalPrice.multiply(new BigDecimal(discount));
return total.add(totalPrice);
}
/**
*折扣选择
*
* @param scan
* @return String discount
*/
private static String getDiscount(Scanner scan) {
int count = scan.nextInt();
String discount = null;
switch (count) {
case 1:
discount = "0.8";
case 2:
discount = "0.5";
case 3:
discount = "0.3";
default:
}
return discount;
}
public static void main(String[] args) {
Scanner scan = new Scanner(System.in);
System.out.print("请输入单价:");
String price = scan.nextLine();
System.out.print("请输入数量:");
String num = scan.nextLine();
System.out.println("请选择折扣:1、八折 2、五折 3、三折");
String discount = getDiscount(scan);
market market = new market();
market.calculateTotalPrice(new BigDecimal(price), new BigDecimal(num), discount);
}
}
下面是策略模式
策略抽象类
public abstract class CashSuperStrategy {
/**
* 收取现金
*
* @param money 原价
* @return BigDecimal 打折后价格
*/
public abstract BigDecimal acceptCash(BigDecimal money);
}
具体策略一
public class ConcreteStrategyOne extends CashSuperStrategy {
/**
* 具体算法实现
* @param money 原价
* @return result 折扣后价格
*/
@Override
public BigDecimal acceptCash(BigDecimal money) {
return money;
}
}
具体策略二
public class ConcreteStrategyTwo extends CashSuperStrategy {
/**
* 输入金额
*/
private BigDecimal moneyCondition;
/**
* 返利金额
*/
private BigDecimal moneyReturn;
ConcreteStrategyTwo(BigDecimal moneyCondition, BigDecimal moneyReturn) {
this.moneyCondition = moneyCondition;
this.moneyReturn = moneyReturn;
}
/**
* 具体策略实现
* @param money 原价
* @return result 折扣后价格
*/
@Override
public BigDecimal acceptCash(BigDecimal money) {
BigDecimal result = money;
if (money.compareTo(moneyCondition) != -1) {
result = money.subtract(moneyReturn);
}
return result;
}
}
具体策略三
public class ConcreteStrategyThree extends CashSuperStrategy {
/**
* 折扣率
*/
private BigDecimal moneyRebate;
/**
* 初始化时带入折扣率
*/
ConcreteStrategyThree(String moneyRebate) {
this.moneyRebate = new BigDecimal(moneyRebate);
}
/**
*
* @param money 原价
* @return result 折扣后价格
*/
@Override
public BigDecimal acceptCash(BigDecimal money) {
return money.multiply(moneyRebate);
}
}
上下文
@Slf4j
public class CashContext {
private CashSuperStrategy cashSuperStrategy;
public CashContext(int type) {
switch (type) {
case 1:
cashSuperStrategy = new ConcreteStrategyOne();
log.info("当前没有活动");
break;
case 2:
cashSuperStrategy = new ConcreteStrategyTwo(new BigDecimal("300"),new BigDecimal("100"));
log.info("当前活动为:满300减100");
break;
case 3:
cashSuperStrategy = new ConcreteStrategyThree("0.8");
log.info("当前活动为:打八折");
break;
default:
}
}
public BigDecimal getResult(BigDecimal money) {
return cashSuperStrategy.acceptCash(money);
}
}
测试类
@Slf4j
public class market {
private static BigDecimal total = new BigDecimal("0.0");
public static void main(String[] args) {
Scanner scan = new Scanner(System.in);
System.out.println("请输入活动类型:1、正常收费 2、满300减100 3、打八折");
int type = scan.nextInt();
System.out.print("请输入单价:");
String goodsPrice = scan.next();
System.out.print("请输入数量:");
String goodsNum = scan.next();
CashContext cashContext = new CashContext(type);
BigDecimal totalPrice = cashContext.getResult(new BigDecimal(goodsPrice)).multiply(new BigDecimal(goodsNum));
total = total.add(totalPrice);
log.info("===============================");
log.info("单价:" + goodsPrice + " 数量:" + goodsNum + " 合计:" + total);
log.info("===============================");
}
}
参考资料: https://blog.csdn.net/tugangkai/article/details/88074288