定义一族算法类,将每个算法分别封装起来,让它们可以互相替换。策略模式可以使算法的变化独立于使用它们的客户端(这里的客户端代指使用算法的代码)。我们知道,工厂模式是解耦对象的创建和使用,观察者模式是解耦观察者和被观察者。策略模式跟两者类似,也能起到解耦的作用,不过,它解耦的是策略的定义、创建、使用这三部分。
策略类的定义比较简单,包含一个策略接口和一组实现这个接口的策略类。因为所有的策略类都实现相同的接口,所以,客户端代码基于接口而非实现编程,可以灵活地替换不同的策略
public interface ISortAlg { void sort(String filePath); }
定义策略实现类
package com.lf.pattern.strategy; public class ConcurrentExternalSort implements ISortAlg{ @Override public void sort(String filePath) { } }
package com.lf.pattern.strategy; public class ExternalSort implements ISortAlg{ @Override public void sort(String filePath) { } }
package com.lf.pattern.strategy; public class QuickSort implements ISortAlg{ @Override public void sort(String filePath) { } }
package com.lf.pattern.strategy; public class MapReduceSort implements ISortAlg{ @Override public void sort(String filePath) { } }
定义策略工厂类,从工厂里取对象
package com.lf.pattern.strategy; import java.util.HashMap; import java.util.Map; /** * 策略工厂类 */ public 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); } }
策略的使用:
package com.lf.pattern.strategy; import java.io.File; public class IfSorter { private static final long GB = 1000 * 1000 * 1000; public void sortFile(String filePath) { // 省略校验逻辑 File file = new File(filePath); long fileSize = file.length(); ISortAlg sortAlg; //消除大量的if/else,让代码结构更优雅 if (fileSize < 6 * GB) { // [0, 6GB) sortAlg = SortAlgFactory.getSortAlg("QuickSort"); } else if (fileSize < 10 * GB) { // [6GB, 10GB) sortAlg = SortAlgFactory.getSortAlg("ExternalSort"); } else if (fileSize < 100 * GB) { // [10GB, 100GB) sortAlg = SortAlgFactory.getSortAlg("ConcurrentExternalSort"); } else { // [100GB, ~) sortAlg = SortAlgFactory.getSortAlg("MapReduceSort"); } sortAlg.sort(filePath); } }
消除大量if/else,代码优雅化、健壮化
package com.lf.pattern.strategy; import java.io.File; import java.util.ArrayList; import java.util.List; 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; } } }
如果不想改动代码,则可以做成注解或者配置,扫描注解或配置加载进list,然后查表法即可