目录:
- 什么是策略模式
- 策略模式能用来干什么
- 策略模式的实现方式
- 场景示例
什么是策略模式
通过定义一系列类似的策略类,并将其分别封装起来,让他们可以互相替换的模式。
策略模式能用来干什么
策略模式可以使算法的变化独立于使用它们的客户端,解耦策略的定义、创建、使用这三部分。
策略模式的实现方式
1、策略的定义
1 /** 2 * 策略接口 3 * 4 * @author zhoude 5 * @date 2020/4/18 19:02 6 */ 7 public interface Strategy { 8 /** 9 * 策略算法接口 10 */ 11 void algorithmInterface(); 12 }
1 /** 2 * 具体的策略A 3 * 4 * @author zhoude 5 * @date 2020/4/18 19:03 6 */ 7 public class ConcreteStrategyA implements Strategy { 8 @Override 9 public void algorithmInterface() { 10 System.err.println("具体的策略A算法的实现"); 11 } 12 }
1 /** 2 * 具体的策略B 3 * 4 * @author zhoude 5 * @date 2020/4/18 19:03 6 */ 7 public class ConcreteStrategyB implements Strategy { 8 @Override 9 public void algorithmInterface() { 10 System.err.println("具体的策略B算法的实现"); 11 } 12 }
2、策略的创建
1 /** 2 * 策略工厂,用于创建具体的策略算法 3 * cache:策略类无状态不需要每次new一个新的 4 * 5 * @author zhoude 6 * @date 2020/4/18 19:07 7 */ 8 public class StrategyFactoryCache { 9 private static final Map<String, Strategy> STRATEGIES = new HashMap<>(); 10 11 static { 12 STRATEGIES.put("A", new ConcreteStrategyA()); 13 STRATEGIES.put("B", new ConcreteStrategyB()); 14 } 15 16 public static Strategy getStrateg(String type) { 17 if (type == null || type.isEmpty()) { 18 throw new IllegalArgumentException("type should not be empty."); 19 } 20 return STRATEGIES.get(type); 21 } 22 }
1 /** 2 * 策略工厂,用于创建具体的策略算法 3 * cache:策略类有状态需要每次new一个新的 4 * 5 * @author zhoude 6 * @date 2020/4/18 19:07 7 */ 8 public class StrategyFactory { 9 public static Strategy getStrateg(String type) { 10 if (type == null || type.isEmpty()) { 11 throw new IllegalArgumentException("type should not be empty."); 12 } 13 14 if ("A".equals(type)) { 15 return new ConcreteStrategyA(); 16 } else if ("B".equals(type)) { 17 return new ConcreteStrategyB(); 18 } 19 20 return null; 21 } 22 }
一般来说若策略是有状态的,那我们可以将创建额对象缓存到工厂类中,用的时候直接返回,如StrategyFactoryCache。
如果是无状态的,那就需要每次new一个新的策略类,StrategyFactory。
3、策略的使用
1 /** 2 * 测试类 3 * 4 * @author zhoude 5 * @date 2020/4/18 19:16 6 */ 7 public class Test { 8 public static void main(String[] args) throws IOException { 9 configLoad(); 10 staticLoad(); 11 } 12 13 /** 14 * 通过加载配置方式方式,动态获取策略类 15 * 16 * @throws IOException exception 17 */ 18 private static void configLoad() throws IOException { 19 Properties properties = new Properties(); 20 properties.load(new FileInputStream("behavior/src/strategy/strategy.properties")); 21 String type = properties.getProperty("strategy.config"); 22 Strategy strategy = StrategyFactoryCache.getStrateg(type); 23 strategy.algorithmInterface(); 24 } 25 26 /** 27 * 静态指定策略类 28 */ 29 private static void staticLoad() { 30 Strategy strategy = StrategyFactory.getStrateg("B"); 31 if (strategy != null) { 32 strategy.algorithmInterface(); 33 } 34 } 35 }
场景示例
场景:根据文件大小排序,文件里面全是整数,且都已逗号分隔。
根据文件不同大小选择不同策略:
- [0, 6G),使用快排
- [6G, 10G),使用外部排序
- [10G, 100G),使用多线程外部排序
- [100G, +无穷),使用MapReduce多机排序
代码示例:https://github.com/mrjdrs/design-patterns/tree/master/behavior/src/strategy/demo2