「手写设计模式」策略模式

1,100 阅读2分钟

理解名词

策略模式(Strategy Design Pattern)是一种行为型模式。在《设计模式》中的定义为:

定义一簇算法类,将每个算法分别封装起来,让它们可以互相替换。策略模式可以使算法的变化独立于使用它们的客户端。

策略这个词在这里可以理解为针对不同问题给出的专门解决办法。在代码中,策略就是根据不同的输入条件,调用其对应的专门的处理函数。

作用

在代码中解耦策略的定义创建使用

  • 定义:包含一个策略接口和一组实现这个接口的策略类

  • 创建:由工厂类完成,封装策略创建的细节

  • 使用:客户端在运行时动态选择使用哪一个策略类

一个误解:策略模式是用来消除ifelse\color{red}{一个误解:策略模式是用来消除if-else}

策略模式本质不是为了消除if-else,真正可用来消除if-else的是查表法,自定义注解。

适用场景

程序中存在大量的if-else语句,根据不同的条件判断执行不同的逻辑,这些逻辑耦合在一个方法中,使程序显得臃肿,逻辑复杂,可读性差,代码难以维护。

代码示例

现在有这样一个需求,实现一个程序,将给定的文件里的所有数字进行排序。根据文件大小不同,我们应该采取不同的排序算法,按文件小到大应采用的算法依次为快排,外部排序,外部并行排序,分布式MapReduce排序。

定义:

// 定义策略类接口,这里是定义一个排序算法接口
public Interface ISortAlg {
	void sort(String filePath); 
}

// 定义排序算法实现类
public class QuickSort implements ISortAlg {
 	@Override
  public void sort(String filePath) {
  	// 快排实现 
  }
}

public class ExternalSort implements ISortAlg {
 	@Override
  public void sort(String filePath) {
  	// 外部排序实现 
  }
}

public class ConcurrentExternalSort implements ISortAlg {
 	@Override
  public void sort(String filePath) {
  	// 外部并行排序实现 
  }
}

public class MapReduceSort implements ISortAlg {
 	@Override
  public void sort(String filePath) {
  	// 分布式排序实现 
  }
}

创建:

// 定义策略工厂来创建策略对象
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) {
   	return algs.get(type); 
  }
}

使用:

public class Sorter {
 	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 (fileSize < 6 * GB) {
     	sortAlg = SortAlgFactory.getSortAlg("QuickSort");
    } else if (fileSize < 10 * GB) {
      sortAlg = SortAlgFactory.getSortAlg("ExternalSort");
    } else if (fileSize < 100 * GB) {
      sortAlg = SortAlgFactory.getSortAlg("ConcurrentExternalSort");
    } else {
      sortAlg = SortAlgFactory.getSortAlg("MapReduceSort");
    }
    
    sortAlg.sort(filePath);
  }
}

可以看到,虽然并没消除if-else,但是使代码变得整洁,逻辑清晰,易维护。