Strategy模式
策略模式介绍:
有一组算法(行为),这些算法(行为)可以封装到共同的接口中,调用者依赖共同的接口,从而当算法被替换时,不影响调用者。
策略模式使用场景:
1.类之间的区别仅在余行为,如:加减乘除操作
2.客户端需要动态选择算法
策略模式和工厂方法的区别:
1.工厂方法返回的是对象
2.策略模式返回具体计算后的值
策略模式结构图:
注意事项:
1.Strategy本身并不决定在合适,使用那种策略,Strategy只能提供算法的封装,以及透明的替换和移除算法。
2.策略模式一般不用于嵌套。
1.半年内交易三次以上,在库龄折扣的基础上,7折销售
2.一年内交易三次以上的,在库龄折扣的基础上,9折销售
以上用装饰模式解决
引入问题:
1.库龄半个月以上的,每顿减5块销售
2.库龄1个月以上的,8折销售
3.半年内交易三次以上,在库龄折扣的基础上,7折销售
4.一年内交易三次以上的,在库龄折扣的基础上,9折销售
5.其余没有折扣
代码设计:
/**
* 折扣计算接口
*/
public interface DiscountStrategy
{
/**
* 折扣计算
* @return 计算后的价钱
*/
BigDecimal calculateDiscount();
}
/**
* 策略消费上下文,持有折扣计算接口
*/
public class DiscountContext
{
private DiscountStrategy strategy;
public DiscountContext(DiscountStrategy strategy){
this.strategy = strategy;
}
public BigDecimal executeDiscount(){
return strategy.calculateDiscount();
}
}
/**
* 库龄半个月的折扣
*/
public class HalfMonthDiscountStrategy implements DiscountStrategy
{
/** 固定折扣价钱 */
private final double FIXED = 5.0;
/** 每顿价格 */
private String price;
/** 吨总数 */
private double tons;
public HalfMonthDiscountStrategy(String price, double tons){
this.price = price;
this.tons = tons;
}
@Override
public BigDecimal calculateDiscount()
{
BigDecimal p = new BigDecimal(price);
return p.multiply(new BigDecimal(Math.abs(tons - FIXED)));
}
}
/**
* 没有折扣
*/
public class NoDiscountStrategy implements DiscountStrategy
{
/** 每顿价格 */
private String price;
/** 吨总数 */
private double tons;
public NoDiscountStrategy(String price, double tons){
this.price = price;
this.tons = tons;
}
@Override
public BigDecimal calculateDiscount()
{
BigDecimal p = new BigDecimal(price);
return p.multiply(new BigDecimal(tons));
}
}
/**
* 一个月的折扣
*/
public class OneMonthDiscountStrategy implements DiscountStrategy
{
/** 八折 */
private final double PERCENT = 0.8;
/** 每顿价格 */
private String price;
/** 吨总数 */
private double tons;
public OneMonthDiscountStrategy(String price, double tons){
this.price = price;
this.tons = tons;
}
@Override
public BigDecimal calculateDiscount()
{
BigDecimal p = new BigDecimal(price);
return p.multiply(new BigDecimal(tons)).multiply(new BigDecimal(PERCENT));
}
}
public static void main(String[] args)
{
long day = 5;
DiscountContext context = null;
if(day < 15)
{
context = new DiscountContext(new HalfMonthDiscountStrategy("400.00", 50.0));
} else if(day >= 15 && day <= 30){
context = new DiscountContext(new OneMonthDiscountStrategy("400.00", 50.0));
} else{
context = new DiscountContext(new NoDiscountStrategy("400.00", 50.0));
}
BigDecimal amount = context.executeDiscount();
}