引言
常用的排序算法有选择排序,插入排序,冒泡排序,快速排序,归并排序,希尔排序,堆排序这7种。假设现在有7个数组,他们分别需要用到这7种排序方式的其中一个进行排序应该怎么办呢。最常见的办法就是写一个这样的工具类
/**
* Created by hao on 2016/6/19.
*/
public class SortHelper {
/**
* 选择排序
* @param array
*/
public static void selectSort(int[] array){
System.out.println("选择排序");
}
/**
* 插入排序
* @param array
*/
public static void insertSort(int[] array){
System.out.println("插入排序");
}
/**
* 冒泡排序
* @param array
*/
public static void bubbleSort(int[] array){
System.out.println("冒泡排序");
}
/**
* 快速排序
* @param array
*/
public static void quickSort(int[] array){
System.out.println("快速排序");
}
/**
* 归并排序
* @param array
*/
public static void mergeSort(int[] array){
System.out.println("归并排序");
}
/**
* 希尔排序
* @param array
*/
public static void shellSort(int[] array){
System.out.println("希尔排序");
}
/**
* 堆排序
* @param array
*/
public static void heapSort(int[] array){
System.out.println("堆排序");
}
}
这种方式是可以满足需求的,但是有个不太好的地方:如果我们现在新增了一种排序算法怎么办呢?必须要修改SortHelper类中的代码然后在其中再加一种排序方式,这是违反我们常说的开闭原则的,而且随着排序算法的逐渐增加,SortHelper也会变得更加臃肿。
策略模式
下面我们引入正题,什么是策略模式呢?策略模式模式就是定义一组算法,将每个方法都封装起来,并且使他们之间可以互换。以上面的排序算法为例,我们可以将这些算法都抽象出来,提供一个统一的接口,每种排序算法都去实现这个接口并在其中实现自己的排序算法。当我们使用某种排序算法的时候就可以直接传入这个算法的实现对象就可以了。下面我们还是用代码实现一遍吧
首先定义一个统一的接口
public interface SortStrategy {
void sort(int[] array);
}
然后每种算法都去实现这个接口
public class SelectSort implements SortStrategy{
@Override
public void sort(int[] array) {
System.out.println("这里实现了选择排序");
}
}
public class InsertSort implements SortStrategy{
@Override
public void sort(int[] array) {
System.out.println("这里实现了插入排序");
}
}
public class BubbleSort implements SortStrategy{
@Override
public void sort(int[] array) {
System.out.println("这里实现了冒泡排序");
}
}
public class MergeSort implements SortStrategy{
@Override
public void sort(int[] array) {
System.out.println("这里实现了归并排序");
}
}
public class ShellSort implements SortStrategy{
@Override
public void sort(int[] array) {
System.out.println("这里实现了希尔排序");
}
}
public class HeapSort implements SortStrategy{
@Override
public void sort(int[] array) {
System.out.println("这里实现了堆排序");
}
}
public class QuickSort implements SortStrategy{
@Override
public void sort(int[] array) {
System.out.println("这里实现了快速排序");
}
}
我们还需要一个类去将这些类封装一下方便调用
public class SortOperator {
private SortStrategy strategy;
public SortOperator(SortStrategy sortStrategy){
this.strategy=sortStrategy;
}
public void Operator(int[] array){
strategy.sort(array);
}
}
下面我们可以测试一下策略模式的效果
public class Test {
public static void main(String[] args){
SortOperator operator1=new SortOperator(new QuickSort());
operator1.Operator(null);
SortOperator operator2=new SortOperator(new MergeSort());
operator2.Operator(null);
}
}
运行后结果
这里实现了快速排序
这里实现了归并排序
凡事有利必有弊,策略模式也一样,策略模式封装了底层的算法,可以非常方便的进行拓展和维护。但相应的代价就是类文件增多同时所有的策略类都需要对外暴露。
另一个角度
当你在学习多态的时候一定看过这样的代码
public abstract class Animal {
abstract void voice();
}
public class Dog extends Animal{
@Override
void voice() {
System.out.println("汪汪。。。");
}
}
public class Cat extends Animal{
@Override
void voice() {
System.out.println("喵喵");
}
}
public class Test {
public static void main(String[] args){
Animal dog=new Dog();
dog.voice();
Animal cat=new Cat();
cat.voice();
}
}
有没有发现这跟策略模式简直一毛一样,策略模式本来就是采用了面向对象的继承和多态机制,并没有什么难以理解的地方,难的往往是你如何才能在繁杂的业务逻辑代码中抽离出策略接口。