策略模式是指根据不同的对象,来采取不同的策略,其实这种场景非常场景。
促销活动中的打折就是最常见的一张。我们会根据这个客户的类型、或者他参与的活动的类型,或者是购物金额的不同采用不同的打折策略。
首先我们定义一个策略接口类
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; } } }