java设计模式之策略

策略模式是指根据不同的对象,来采取不同的策略,其实这种场景非常场景。

促销活动中的打折就是最常见的一张。我们会根据这个客户的类型、或者他参与的活动的类型,或者是购物金额的不同采用不同的打折策略。

首先我们定义一个策略接口类

public interface Strategy {
    Double discount(Double Double);
}

//普通用户打折策略
public class CommonStrategy implements Strategy {
    @Override
    public Double discount(Double amount) {
        return amount;
    }
}

//会员用户打折策略
public class MemberStrategy implements Strategy {
    @Override
    public Double discount(Double amount) {
        return 0.9 * amount;
    }
}

//vip用户打折策略
public class VipStrategy implements Strategy {
    @Override
    public Double discount(Double amount) {
        return 0.8 * amount;
    }
}

用户类型的枚举类

public enum  CustomerEnum {
    COMMON,MEMBER,VIP;
}

我们定义一个工厂类,根据用户类型返回不同的策略

public class StrategyFactory {

    private static Map<CustomerEnum, Strategy> map = new ConcurrentHashMap<>();

    static {
        map.put(CustomerEnum.COMMON, new CommonStrategy());
        map.put(CustomerEnum.MEMBER, new MemberStrategy());
        map.put(CustomerEnum.VIP, new VipStrategy());
    }

    /**
     * 这样只不过把业务逻辑中的if/else挪到了工厂类中
     *
     * @param userType
     * @return
     */
    public static Strategy getStrategy(CustomerEnum userType) {
        Strategy strategy;
        if (userType == CustomerEnum.COMMON) {
            strategy = new CommonStrategy();
        } else if (userType == CustomerEnum.MEMBER) {
            strategy = new MemberStrategy();
        } else {
            strategy = new VipStrategy();
        }
        return strategy;
    }

    /**
     * 通过map构造一张哈希表,将类型和策略映射起来,减少if/else和switch的出现
     * @param userType
     * @return
     */
    public static Strategy getStrategyByType(CustomerEnum userType) {
        return map.get(userType);
    }
}

订单类和入口类

@Data
public class Order {
    private CustomerEnum userType;
    private double amount;
}

//入口类
public class Application {
    public static void main(String[] args) {
        Order order = new Order();
        order.setAmount(10000.0);
        order.setUserType(CustomerEnum.VIP);
        Strategy strategy = StrategyFactory.getStrategy(order.getUserType());
        double payAmount= strategy.discount(order.getAmount());
        System.out.println(payAmount);
    }
}

 

可能有人问,如果我的if/else里不是类型,而是区间范围怎么办,也是可以解决的,看下面代码

public class Sorter {
  private static final long GB = 1000 * 1000 * 1000;
  private static final List<AlgRange> algs = new ArrayList<>();
  static {
    algs.add(new AlgRange(0, 6*GB, SortAlgFactory.getSortAlg("QuickSort")));
    algs.add(new AlgRange(6*GB, 10*GB, SortAlgFactory.getSortAlg("ExternalSort")));
    algs.add(new AlgRange(10*GB, 100*GB, SortAlgFactory.getSortAlg("ConcurrentExternalSort")));
    algs.add(new AlgRange(100*GB, Long.MAX_VALUE, SortAlgFactory.getSortAlg("MapReduceSort")));
  }

  public void sortFile(String filePath) {
    // 省略校验逻辑
    File file = new File(filePath);
    long fileSize = file.length();
    ISortAlg sortAlg = null;
    for (AlgRange algRange : algs) {
      if (algRange.inRange(fileSize)) {
        sortAlg = algRange.getAlg();
        break;
      }
    }
    sortAlg.sort(filePath);
  }

  private static class AlgRange {
    private long start;
    private long end;
    private ISortAlg alg;

    public AlgRange(long start, long end, ISortAlg alg) {
      this.start = start;
      this.end = end;
      this.alg = alg;
    }

    public ISortAlg getAlg() {
      return alg;
    }

    public boolean inRange(long size) {
      return size >= start && size < end;
    }
  }
}

 

posted @ 2022-01-25 17:12  Mars.wang  阅读(65)  评论(0编辑  收藏  举报