策略模式
策略模式,就是定义一组策略算法,将每一个策略算法封装成一个类,使它们之间可以相互替换,取代大量的if…else或switch判断
三个角色
- Strategy 抽象策略对象(接口/抽象类)
- ConcreteStrategy 具体策略算法对象
- Context 封装角色(具体计算)
例子: 商品价格根据会员等级打折扣
假设会员等级有三个级别,一级会员商品价格打九折,二级打八折,三级打七折,计算不同会员等级下对应商品的实际价格。
- 定义抽象策略对象(Strategy)
/**
* 策略接口
* @author River
* @date 2018/7/17
*/
public interface Strategy {
/**
* 获取打折后的价格
* @return
*/
double getDiscount(double price);
}
- 定义会员一、二、三
public class ConcreteStrategyOne implements Strategy {
@Override
public double getDiscount(double price) {
return price * 0.9;
}
}
public class ConcreteStrategyTwo implements Strategy {
@Override
public double getDiscount(double price) {
return price * 0.8;
}
}
public class ConcreteStrategyThree implements Strategy {
@Override
public double getDiscount(double price) {
return price * 0.7;
}
}
- 定义封装角色Context
封装角色Context具有策略对象(Strategy)的引用,公开根据具体策略对象计算商品实际价格的方法
public class Context {
private Strategy strategy;
public Context(Strategy strategy) {
this.strategy = strategy;
}
public double computePrice(double price) {
return strategy.getDiscount(price);
}
}
- 具体使用
public class Main {
public static void main(String[] args) {
double price = 20;
System.out.println("商品原价:" + price);
System.out.println();
Context context = new Context(new ConcreteStrategyOne());
System.out.println("一级会员购买实际价格:" + context.computePrice(price));
System.out.println();
context = new Context(new ConcreteStrategyTwo());
System.out.println("二级会员购买实际价格:" + context.computePrice(price));
System.out.println();
context = new Context(new ConcreteStrategyThree());
System.out.println("三级会员购买实际价格:" + context.computePrice(price));
}
}
- 结果如下
商品原价:20.0
一级会员购买实际价格:18.0
二级会员购买实际价格:16.0
三级会员购买实际价格:14.0
总结
优点:能省略if…else,switch判断,如果新增了新的会员等级,只需要新增具体会员等级类,不需修改现有代码,符合开闭原则
缺点:会产生大量的类
补充
可以使用jdk8自带的Function来取代抽象策略类
- 定义会员一、二
public class One implements Function<Double, Double> {
private static final Double ONE_DISCOUNT = 0.9;
@Override
public Double apply(Double price) {
return price * ONE_DISCOUNT;
}
}
public class Two implements Function<Double, Double> {
private static final Double TWO_DISCOUNT = 0.8;
@Override
public Double apply(Double price) {
return price * TWO_DISCOUNT;
}
}
- 定义封装角色Context
public class Context {
private Function<Double, Double> function;
public Context(Function<Double, Double> function) {
this.function = function;
}
public Double computePrice(Double price) {
return function.apply(price);
}
}
- 具体使用
public class Context {
private Function<Double, Double> function;
public Context(Function<Double, Double> function) {
this.function = function;
}
public Double computePrice(Double price) {
return function.apply(price);
}
}
- 结果如下
商品原价:20.0
一级会员购买实际价格:18.0
二级会员购买实际价格:16.0