策略模式

2021-04-25  本文已影响0人  lj72808up

1. 什么是策略模式

2. 解耦三方

1. 策略(算法)的定义

策略模式中, 强调的事一组算法可以相互替换. 因此, 策略是接口的一组实现

 //  策略. 算法的接口
 public interface Strategy {
   void algorithmInterface();
 }

 public class ConcreteStrategyA implements Strategy {
   @Override
   public void  algorithmInterface() {
     //具体的算法...
   }
 }

 public class ConcreteStrategyB implements Strategy {
   @Override
   public void  algorithmInterface() {
     //具体的算法...
   }
 }

2. 策略的创建

所谓策略的创建, 就是根据不同情况, 选择不同算法(策略)进行调用. 可以使用工厂类创建算法(策略)对象. 这里需要注意的是, 策略分为有状态和无状态的

  public class StrategyFactory {
    private static final Map<String, Strategy> strategies = new HashMap<>();

    static {
      strategies.put("A", new ConcreteStrategyA());
      strategies.put("B", new ConcreteStrategyB());
    }

    public static Strategy getStrategy(String type) {
      if (type == null || type.isEmpty()) {
        throw new IllegalArgumentException("type should not be empty.");
      }
      return strategies.get(type);
    }
  }

3. 用 for 消除大量的 if-else 判断使用哪种策略的逻辑

我们看到, 当策略对象不能简单的通过查表法从工厂类中获取时, 工厂类的 getStrategy() 就会出现大量的判断逻辑. 这种实现方式相当于把原来的 if-else 分支逻辑,从调用方转移到策略的创建方.
比如, 有一个需求: 对文件排序. 但根据文件大小的不同, 会选择内存排序, 多线程的外排序, mapreduce 排序这3个不同算法. 策略的选取已经不是简单的类型判断了, 怎么避免 if-else 的出现呢 ?

interface ISortAlg {
    void sort(String filePath);
}

class QuickSort implements ISortAlg {
    @Override
    public void sort(String filePath) {
        //...
    }
}

class ExternalSort implements ISortAlg {
    @Override
    public void sort(String filePath) {
        //...
    }
}

class ConcurrentExternalSort implements ISortAlg {
    @Override
    public void sort(String filePath) {
        //...
    }
}

class MapReduceSort implements ISortAlg {
    @Override
    public void sort(String filePath) {
        //...
    }
}

class SortAlgFactory {
    private static final Map<String, ISortAlg> algs = new HashMap<>();

    static {
        algs.put("QuickSort", new QuickSort());
        algs.put("ExternalSort", new ExternalSort());
        algs.put("ConcurrentExternalSort", new ConcurrentExternalSort());
        algs.put("MapReduceSort", new MapReduceSort());
    }

    public static ISortAlg getSortAlg(String type) {
        if (type == null || type.isEmpty()) {
            throw new IllegalArgumentException("type should not be empty.");
        }
        return algs.get(type);
    }
}

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;
        /** 原先的 if-else 判断, 改成 for 遍历每个策略, 判断策略调用条件是否成立 */
        for (AlgRange algRange : algs) {
            if (algRange.inRange(fileSize)) {
                sortAlg = algRange.getAlg();
                break;
            }
        }
        sortAlg.sort(filePath);
    }

    /** Algorithm 范围, 封装策略和策略调用的条件 */
    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;
        }
    }
}
上一篇下一篇

猜你喜欢

热点阅读