策略模式的书面解释:定义算法簇,分别封装起来,让它们之间可以互相替换。此模式让算法的变化独立于使用算法的客户。 策略模式的通俗解释:通过抽象、封装,实现某种算法/策略的动态替换。

模式组成

  • 环境(Context)角色:持有一个Strategy的引用。
  • 抽象策略(Strategy)角色:这是一个抽象角色,通常由一个接口或抽象类实现。此角色给出所有的具体策略类所需的接口。
  • 具体策略(ConcreteStrategy)角色:包装了相关的算法或行为。

应用场景

  • 自定义排序
  • 游戏角色行为策略
  • 通信协议中的封包与拆包算法

实现方式

动物的自定义排序问题

设计动物游戏中,需要对动物进行排序显示,各类动物具有不同的比较算法,比如猫可以根据身高或者体重进行排序。

示例实现代码

定义动物:Cat

public class Cat {
    int weight, height;

    public Cat(int weight, int height) {
        this.weight = weight;
        this.height = height;
    }

    @Override
    public String toString() {
        return "Cat{" +
                "weight=" + weight +
                ", height=" + height +
                '}';
    }
}

定义抽象策略角色:Comparator

public interface Comparator<T> {
    int compare(T o1, T o2);
}

定义具体策略角色1:CatWeightComparator

public class CatWeightComparator implements Comparator<Cat> {
    @Override
    public int compare(Cat o1, Cat o2) {
        if(o1.weight < o2.weight) return -1;
        else if (o1.weight > o2.weight) return 1;
        else return 0;
    }
}

定义具体策略角色2:CatHeightComparator

public class CatHeightComparator implements Comparator<Cat> {
    @Override
    public int compare(Cat o1, Cat o2) {
        if(o1.height > o2.height) return -1;
        else if (o1.height < o2.height) return 1;
        else return 0;
    }
}

定义环境角色:Sorter

public class Sorter<T> {

    public void sort(T[] arr, Comparator<T> comparator) {
        for(int i=0; i<arr.length - 1; i++) {
            int minPos = i;
            for(int j=i+1; j<arr.length; j++) {
                minPos = comparator.compare(arr[j],arr[minPos])==-1 ? j : minPos;
            }
            swap(arr, i, minPos);
        }
    }
    void swap(T[] arr, int i, int j) {
        T temp = arr[i];
        arr[i] = arr[j];
        arr[j] = temp;
    }
}

也可以将Comparator实例作为Sorter的成员变量,便于进行动态设置

客户端调用示例:

public static void main(String[] args) {
    Cat[] a = {new Cat(3, 3), new Cat(5, 5), new Cat(1, 1)};
    Sorter<Cat> sorter = new Sorter<>();
    sorter.sort(a, new CatHeightComparator());
		//sorter.sort(a, new CatWeightComparator());
    System.out.println(Arrays.toString(a));
}

总结

策略模式的精华是对算法/策略的抽象,自定义排序是最典型的应用场景。当你意识到待解决的问题中存在某种算法/策略,需要动态替换,就可以考虑套用该模式了。

参考资料:

马士兵老师-设计模式

《Head First设计模式》