策略模式学习记录

概要:

以不同场景下的排序需求作为例子进行展示,如何使用策略模式一步一步提升程序拓展性

注:排序方法使用冒泡排序


版本1:直接对整型数组进行排序

main方法

int[] arr = {1,5,2,3,6,4};
// 调用排序方法,最初版本
Sorter sorter = new Sorter();
sorter.sort(arr);
// 输出结果 [1, 2, 3, 4, 5, 6]
System.out.println(Arrays.toString(arr));

Sorter 类

/**
 * 排序处理。支持各种对象的排序。参考 java.comparable
 */
public class Sorter {

    /**
     * 排序方法 1.0
     * 选择排序,依次找到每次循环的最小值并固定下来
     */
    void sort(int[] arr) {
        for (int i = 0; i < arr.length - 1; i++) {
            int minIndex = i;

            for (int j = i+1; j < arr.length; j++) {
                minIndex = arr[minIndex] > arr[j] ? j : minIndex;
            }
            swap(arr, i, minIndex);
        }
    }

    private static void swap(int[] arr, int present, int minIndex) {
        int temp = arr[present];
        arr[present] = arr[minIndex];
        arr[minIndex] = temp;
    }

}

代码分析:

  1. 拓展性弱,排序只能对整型数组进行排序
  2. 简单直接,目标明确

版本2:支持对自定义类(狗狗)数组进行排序

main方法

        Dog[] dogs = {new Dog(5), new Dog(2),new Dog(7),new Dog(3),new Dog(4)};
        // 使用第二版sorter
        Sorter2 sorter2 = new Sorter2();
        sorter2.sort(dogs);
        // 输出结果 [Dog{cost=2}, Dog{cost=3}, Dog{cost=4}, Dog{cost=5}, Dog{cost=7}]
        System.out.println(Arrays.toString(dogs))

Dog类

public class Dog {

    /**
     * 狗狗开销
     */
    private int cost;

    public Dog(int cost) {
        this.cost = cost;
    }

    /**
     * 对狗狗进行排序
     *
     * @return 排序结果 当前比dog小,返回-1;当前与dog相等,返回0;当前比dog大,则返回1
     */
    public int compareTo(Dog dog) {
        if (dog.cost > this.cost) {
            return -1;
        } else if (dog.cost == this.cost) {
            return 0;
        }
        return 1;
    }

    @Override
    public String toString() {
        return "Dog{" +
                "cost=" + cost +
                '}';
    }
}

Sorter2

/**
 * 排序第二版。支持狗,或者某种特定实体类的排序
 * 由此,我们需要:
 * 1. 入参为特定实体类的数组
 * 2. 实体类自行定义个排序方法
 */
public class Sorter2 {

    /**
     * 排序方法 2.0
     * 选择排序,依次找到每次循环的最小值并固定下来
     */
    void sort(Dog[] dogs) {
        for (int i = 0; i < dogs.length - 1; i++) {
            int minIndex = i;

            for (int j = i+1; j < dogs.length; j++) {
                // 使用dog的排序方法进行排序
                minIndex = dogs[minIndex].compareTo(dogs[j]) < 0 ? minIndex : j;
            }
            swap(dogs, i, minIndex);
        }
    }

    private static void swap(Dog[] dogs, int present, int minIndex) {
        Dog temp = dogs[present];
        dogs[present] = dogs[minIndex];
        dogs[minIndex] = temp;
    }
}

代码分析:

  1. 拓展性弱,排序只能对特定自定义类数组进行排序
  2. 代码稍微复杂,实体类实现了compareTo方法

版本3:支持多种自定义类的排序

main 方法

        Dog3[] dog3 = {new Dog3(5), new Dog3(2),new Dog3(7),new Dog3(3),new Dog3(4)};
        Cat3[] cat3 = {new Cat3(5), new Cat3(2),new Cat3(7),new Cat3(3),new Cat3(4)};
        Sorter3 sorter3 = new Sorter3();
        sorter3.sort(dog3);
        sorter3.sort(cat3);
        // 排序结果
        //[Dog3{age=7}, Dog3{age=5}, Dog3{age=4}, Dog3{age=3}, Dog3{age=2}]
        //[Cat3{age=7}, Cat3{age=5}, Cat3{age=4}, Cat3{age=3}, Cat3{age=2}]
        System.out.println(Arrays.toString(dog3));
        System.out.println(Arrays.toString(cat3));

Dog3 (与Cat3同)

public class Dog3 implements SortComparable<Dog3> {

    private int age;

    public Dog3(int age) {
        this.age = age;
    }

    @Override
    public String toString() {
        return "Dog3{" +
                "age=" + age +
                '}';
    }


    @Override
    public int compareTo(Dog3 o) {
        if (o.age > this.age) {
            return -1;
        } else if (o.age == this.age) {
            return 0;
        }
        return 1;
    }
}

SortComparable 接口,指定排序行为

public interface SortComparable<T> {

    /**
     * 排序行为, T 为需要指定类型的泛型
     */
    int compareTo(T t);

}

Sorter3

/**
 * 排序第三版。同时支持狗,猫等多种实体类排序
 * 由此,我们需要:
 * 1. 入参为泛型实体类的数组
 * 2. 需要实体类存在同一个排序行为(接口)
 * 3. 实体类自行实现这个排序行为
 */
public class Sorter3 {

    /**
     * 排序方法 3.0
     * 选择排序,依次找到每次循环的最小值并固定下来
     */
    void sort(SortComparable[] arr) {

        for (int i = 0; i < arr.length - 1; i++) {
            int minIndex = i;
            for (int j = i+1; j < arr.length; j++) {
                minIndex = arr[j].compareTo(arr[minIndex]) == -1 ? minIndex : j;
            }
            swap(arr, i, minIndex);
        }
    }

    private void swap(SortComparable[] t, int present, int minIndex) {
        SortComparable temp = t[present];
        t[present] = t[minIndex];
        t[minIndex] = temp;
    }
}


代码分析:

  1. 拓展性强,可以对实现了SortComparable接口的各种实体类数组进行排序
  2. 代码复杂,实体类实现了compareTo这一个可变的行为
  3. 实体类与排序行为间耦合度较高,如果需要改变比较策略,则会改动到实体类本身

版本4:支持多种自定义类排序的同时,支持自定义排序策略

main 方法

        // 使用猫咪比较器,对猫咪数组进行排序。
        Cat4[] cat4 = {new Cat4(5, 2), new Cat4(2, 4),new Cat4(1, 3),new Cat4(5, 5),new Cat4(2, 6)};
        Sorter4<Cat4> sorter4 = new Sorter4<>();
        sorter4.sort(cat4, new Cat4SortCompareTor());
        // 版本4-猫咪重量排序结果 [Cat4{high=5, weight=2}, Cat4{high=1, weight=3}, Cat4{high=2, weight=4}, Cat4{high=5, weight=5}, Cat4{high=2, weight=6}]
        System.out.println(Arrays.toString(cat4));

        System.out.println("=======版本4-猫咪高度排序======");
        // 版本4-猫咪高度排序结果 [Cat4{high=1, weight=3}, Cat4{high=2, weight=6}, Cat4{high=2, weight=4}, Cat4{high=5, weight=2}, Cat4{high=5, weight=5}]
        sorter4.sort(cat4, new Cat4HighSortCompareTor());
        System.out.println(Arrays.toString(cat4));


        // 使用蚊子比较器,对蚊子数组进行排序。
        Mosquito[] Mosquito = {new Mosquito(5, 2), new Mosquito(2, 4),new Mosquito(1, 3),new Mosquito(5, 5),new Mosquito(2, 6)};
        Sorter4<Mosquito> sorter5 = new Sorter4<>();
        sorter5.sort(Mosquito, new MosquitoSpeedSortCompareTor());
        // 版本4蚊子速度排序: [Mosquito{speed=5, size=5}, Mosquito{speed=5, size=2}, Mosquito{speed=2, size=6}, Mosquito{speed=2, size=4}, Mosquito{speed=1, size=3}]
        System.out.println(Arrays.toString(Mosquito));

cat4 (与Mosquito类似),回归了实体本质

public class Cat4 {

    private int high;
    private int weight;

    public Cat4(int high, int weight) {
        this.high = high;
        this.weight = weight;
    }

    public int getHigh() {
        return high;
    }

    public void setHigh(int high) {
        this.high = high;
    }

    public int getWeight() {
        return weight;
    }

    public void setWeight(int weight) {
        this.weight = weight;
    }

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

SortCompareTor 接口,指定排序行为

public interface SortCompareTor<T> {
    int compare(T t, T t1);
}

Cat4HighSortCompareTor 猫咪高度排序策略,其它排序策略实现类似

/**
 * Cat4 排序策略,使用高度进行排序
 */
public class Cat4HighSortCompareTor implements SortCompareTor<Cat4> {
    @Override
    public int compare(Cat4 t1, Cat4 t2) {
        if (t1.getHigh() < t2.getHigh()) {
            return -1;
        } else if (t1.getHigh() > t2.getHigh()) {
            return 1;
        }
        return 0;
    }
}

Sorter4

/**
 * 排序第四版。同时支持狗,猫等多种实体类排序,并且支持自定义排序方式
 * 由此,我们需要:
 * 1. 入参为泛型实体类的数组
 * 2. 实体类的排序方式(比较策略)。 作为策略模式核心,每个排序策略都是一个单独的类(开闭原则,就排序方式而言。策略模式隔离了变化点)
 */
public class Sorter4<T> {
    /**
     * 排序方法 4.0
     * 选择排序,依次找到每次循环的最小值并固定下来
     * @param arr 需要排序的数组
     * @param compareTor 排序方式
     */
    void sort(T[] arr, SortCompareTor<T> compareTor) {
        for (int i = 0; i < arr.length - 1; i++) {
            int minIndex = i;
            for (int j = i+1; j < arr.length; j++) {
                minIndex = compareTor.compare(arr[minIndex],arr[j]) == -1 ? minIndex : j;
            }
            swap(arr, i, minIndex);
        }
    }

    private void swap(T[] t, int present, int minIndex) {
        T temp = t[present];
        t[present] = t[minIndex];
        t[minIndex] = temp;
    }
}

代码分析:

  1. 拓展性极强,在当前排序场景下已经隔离了几乎所有变化点,后续无论是排序需求还是排序对象出现变化,排序类本身都可以做到不变。
  2. 代码间调用复杂,但逻辑清晰。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值