策略模式简介:

策略模式对应于解决某一个问题的一个算法族(多个算法),允许用户从该算法族中任选一种算法解决某一问题;同时,可以方便的更换算法或用户自定义新的算法;并且由用户决定调用最终使用哪个算法。
应用场景如下:
模拟商场购物场景,不同会员等级的客户会有不同的打折策略。具体代码如下:

  1. public class Strategy {
  2. /**
  3. * 根据不同的用户对商品打折
  4. * @param price
  5. * @return
  6. */
  7. public BigDecimal discounted(VipLevel vipLevel,BigDecimal price){
  8. switch (vipLevel){
  9. case PT:
  10. return price.multiply(new BigDecimal(0.6));
  11. case GOLD:
  12. return price.multiply(new BigDecimal(0.7));
  13. case SILVER:
  14. return price.multiply(new BigDecimal(0.8));
  15. case COPPER:
  16. return price.multiply(new BigDecimal(0.9));
  17. default:
  18. return null;
  19. }
  20. }
  21. }

枚举类,定义会员等级

  1. /**
  2. * 会员等级
  3. */
  4. public enum VipLevel {
  5. PT("pt"),
  6. GOLD("gold"),
  7. SILVER("silver"),
  8. COPPER("copper");
  9. String level;
  10. VipLevel(String level) {
  11. this.level = level;
  12. }
  13. }

虽然有点样子了,但这种实现方式肯定不是我们最终想要的,原因有以下三点:
1.每次新增算法都要改这个类,违反开闭原则;
2.策略多了非常不好维护;
3.业务和策略耦合在一起
所以我们来将其改造成真正的策略模式:
我们先定义一个策略接口:
该方法就是说,传进来一个原价格,我根据具体的实现返回给一个打折后的价格。

  1. public interface Strategy {
  2. BigDecimal discounted(BigDecimal price);
  3. }

策略模式 - 图1
image.png
编写几个实现:
黄金会员

  1. public class GoldStrategy implements Strategy {
  2. @Override
  3. public BigDecimal discounted(BigDecimal price) {
  4. return price.multiply(new BigDecimal(0.7));
  5. }
  6. }

青铜会员

  1. public class CopperStrategy implements Strategy {
  2. @Override
  3. public BigDecimal discounted(BigDecimal price) {
  4. return price.multiply(new BigDecimal(0.9));
  5. }
  6. }

既然销售策略有了,现在我们再定义一个销售职员接口:
销售人员只关注价格,不关注算法。

  1. /**
  2. * 销售员接口
  3. *
  4. */
  5. public interface Saler {
  6. BigDecimal coculate(BigDecimal price);
  7. }

定义一个抽象类,继承这个抽象类的子类都需要带有一个策略,白话就是说这一类的销售人员都需要使用实现了Strategy接口的策略去计算价格。

  1. public abstract class ProductionSaler implements Saler{
  2. protected Strategy strategy;
  3. public ProductionSaler(Strategy strategy) {
  4. this.strategy = strategy;
  5. }
  6. }

具体的销售人员:

  1. public class RealSaler extends ProductionSaler{
  2. public RealSaler(Strategy strategy) {
  3. super(strategy);
  4. }
  5. @Override
  6. public BigDecimal coculate(BigDecimal price) {
  7. return strategy.discounted(price);
  8. }
  9. }

测试类:

  1. public class Test {
  2. public static void main(String[] args) {
  3. Saler saler = new RealSaler(new CopperStrategy());
  4. System.out.println(saler.coculate(new BigDecimal(60)));
  5. }
  6. }

策略模式 - 图2