java 23 种设计模式学习笔记_2_策略模式

策略模式

学习视频: 23种设计模式,终于有人用一个项目讲清楚了,保姆级教程通俗易懂

1. 场景:对int数组进行排序

创建一个Sorter类对int数组进行排序

main方法:

public class Main {
    public static void main(String[] args) {
        int[] arr = {4, 2, 5, 1};
        Sorter sorter = new Sorter();
        sorter.sort(arr);
        System.out.println(Arrays.toString(arr));
    }
}

Sorter类:

public class Sorter {
    public void sort(int[] arr) {
        for (int i=0; i<arr.length; i++) {
            int minPos = i;
            for (int j=i+1; j<arr.length; j++) {
                if (arr[j] < arr[minPos]) {
                    minPos = j;
                }
            }
            swap(arr, i, minPos);
        }
    }
    public static void swap(int[] arr, int i, int minPos) {
        int temp = arr[i];
        arr[i] = arr[minPos];
        arr[minPos] = temp;
    }
}

问题: 如果要对double类型数组进行排序怎么办?甚至如果待排序的数组是个自定义对象数组怎么办呢?总不能一直修改Sorter类,扩展sort方法吧,这不是一个好的方式。

解决办法

  1. 排序核心计算是比较,比较的逻辑与Sorter类脱钩,将逻辑内嵌到待排序的对象中;
  2. Sorter类的比较方法的入参如何动态可变,引入接口,让比较的对象都继承此接口(comparaTo方法)。
    也就是说,Sorter类和待排序的数组,通过这个接口来关联,这个接口赋予对象可比较的特性。

2. 扩展:对自定义对象数组进行排序

定义接口*(另外参考 java.lang 包中的 Comparable 接口)*

public interface Comparable<T> {
    int compareTo(T o);
}

这里使用了泛型,因为 CompareTo 方法中参数类型不是固定的,使用泛型就相当于定义了一系列的接口,方便了很多

待排序的自定义对象类,继承上面接口

public class Cat implements Comparable<Cat> {
    int size;
    int weight;
    
    public Cat(int size, int weight) {
        this.size = size;
        this.weight = weight;
    }
    
    @Override
    public int compareTo(Cat c) {
        return Integer.compare(this.size, c.size);
    }
    
    @Override
    public String toString() {
        return "Cat{" +
                "size=" + size +
                ", weight=" + weight +
                '}';
    }
}

main方法

public class Main {
    public static void main(String[] args) {
        Cat[] arr = {new Cat(3, 2), new Cat(4, 3), new Cat(2, 4)};
        Sorter sorter = new Sorter();
        sorter.sort(arr);
        System.out.println(Arrays.toString(arr));
    }
}

问题:如果对象数组的比较方式不固定怎么办?比如要求 Cat 按照 weight 属性来做为比较的依据该怎么办呢? 还需要修改现有的代码,做不到对修改关闭对扩展开放。

3 再扩展: 不同的比较策略

将比较的特性和对象拆开,抽象出一个comparator接口,Sorter类中的排序方法分别传入对象数组和comparator对象两个参数。

这样,对象和排序彻底解耦,对象的定义中不会涉及到比较的逻辑。

comparator接口(java.lang包下的Comparator接口

public interface Comparator<T> {
    int compare(T a, T b);
}

接口实现

public class CatSizeComparator implements Comparator<Cat> {
    @Override
    public int compare(Cat a, Cat b) {
        return Integer.compare(a.size, b.size);
    }
}

Sorter

public class Sorter<T> {
    public void sort(T[] arr, Comparator<T> c) {
        for (int i=0; i<arr.length; i++) {
            int minPos = i;

            for (int j=i+1; j<arr.length; j++) {
                if (c.compare(arr[j], arr[minPos]) == -1) {
                    minPos = j;
                }
            }

            swap(arr, i, minPos);
        }
    }

    public void swap(T[] arr, int i, int minPos) {
        T temp = arr[i];
        arr[i] = arr[minPos];
        arr[minPos] = temp;
    }
}

main方法

public class Main {
    public static void main(String[] args) {
        Cat[] arr = {new Cat(3, 2), new Cat(4, 3), new Cat(2, 4)};
        Sorter sorter = new Sorter();
        sorter.sort(arr, new CatSizeComparator());
        System.out.println(Arrays.toString(arr));
    }
}

这样,如果要用 Catweight 属性来进行比较,就不需要修改现有的代码,只需要新加一个类继承 Comparator 接口即可。

或者更简单的直接使用匿名类,更容易扩展了,如下:

public class Main {
    public static void main(String[] args) {
        Cat[] arr = {new Cat(3, 2), new Cat(4, 3), new Cat(2, 4)};
        Sorter<Cat> sorter = new Sorter<>();
        sorter.sort(arr, (a, b) -> Integer.compare(a.weight, b.weight));
        System.out.println(Arrays.toString(arr));
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值