mybloger

  博客园  :: 首页  :: 新随笔  :: 联系 :: 订阅 订阅  :: 管理

策略模式

应用场景:comparator

先看需求:

实现一个排序器,要求可以对传入的任意类型数组都进行排序

猫数组排序,狗数组排序,只要有大小关系就可以排序,而这个大小关系是我们人为定义的,如狗的规则可以是饭量小的排前面,猫的规则是体重小的排前面等

先看排序器类:就一个简单的公共排序方法,里边使用的一个简单的选择排序

package org.ali.strategy;

/**
 * Author: lury
 * Date: 2022-09-04 10:52
 */
public class Sorter {

    public static void sort(Comparable[] arr) {
        for (int i = 0;i < arr.length - 1;i++) {
            int minPos = i;

            for (int j = i + 1;j < arr.length;j++) {
                minPos = arr[j].CompareTo(arr[minPos]) == -1 ? j : minPos;
            }

            swap(arr,i,minPos);
        }
    }

    static void swap(Comparable[] arr,int i,int j){
        Comparable temp = arr[i];
        arr[i] = arr[j];
        arr[j] = temp;
    }
}

上面代码可能很多人会有疑问,怎么传的是Comoarable数组?

这就是java设计模式的精华了,要保证代码的通用性,一定要想到接口(多态)。所谓java的设计模式,其实就是接口的各种玩法

我们先看看这个接口

package org.ali.strategy;

/**
 * Author: lury
 * Date: 2022-09-04 10:51
 */
public interface Comparable {
    int CompareTo(Object o);
}

接口是什么?接口描述的是一些事物所具有的共同特征,Comparable即顾名思义是指具有可比较性的一类事物,猫类实现这个接口表示的是猫是可比较的,即可以排序的,狗也如此。只是它们实现不一样,即多态

下面是猫狗类,重点看一下compareTo方法即可

package org.ali.strategy;

/**
 * Author: lury
 * Date: 2022-09-04 11:00
 */
public class Cat implements Comparable{
    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 +
                '}';
    }


    @Override
    public int CompareTo(Object o) { // 重点在这,其他不用看
       Cat cat = (Cat) o;
       if (this.weight < cat.weight) return -1;
       else if (this.weight > cat.weight) return 1;
       else return 0;
    }
}


package org.ali.strategy;

/**
 * Author: lury
 * Date: 2022-09-04 11:06
 */
public class Dog implements Comparable {

    int foot;// 饭量

    @Override

    public int CompareTo(Object o) {
        Dog d = (Dog)o; // 这里还有些异常,o传进来如果是cat,会报ClassCastException
        if (this.foot < d.foot) return -1;
        else if (this.foot > d.foot) return 0;
        else return 0;
    }

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

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

下面是测试

public class Main {
    public static void main(String[] args) {
        Cat[] cats = {new Cat(4,3),new Cat(3,4)};
        Dog[] dogs = {new Dog(2),new Dog(4)};

        Sorter.sort(cats);
        Sorter.sort(dogs);
        System.out.println(Arrays.toString(cats));
        System.out.println(Arrays.toString(dogs));


    }
}

![image-20220904113413541](D:\Download\尚硅谷\msb\designer pattern\img\image-20220904113413541.png)

泛型优化,保证谁用compare方法,就传什么类型参数,比如猫调用,就只能传猫类型,而不会传狗类型,这样就不会出现类转换异常了

package org.ali.strategy;

/**
 * Author: lury
 * Date: 2022-09-04 10:51
 */
public interface Comparable<T> { 
    int CompareTo(T o);
}

修改猫狗后的代码

public class Cat implements Comparable<Cat>{
    int weight,height;

    @Override
    public int CompareTo(Cat cat) {
        if (this.weight < cat.weight) return -1;
        else if (this.weight > cat.weight) return 1;
        else return 0;
    }
    ...
}

public class Dog implements Comparable<Dog> {

    int foot;// 饭量

    @Override
    public int CompareTo(Dog d) {
        if (this.foot < d.foot) return -1;
        else if (this.foot > d.foot) return 0;
        else return 0;
    }
    ...
}

搞这么久,其实这还没到策略模式哈,我们实现的Comparable,而策略模式体现在Comparator,不过,别急,

设计模式理论上都差不多的,其最终目的都是帮助我们写出优雅以及便于维护的代码

现在正式进入策略模式

先说以下Comparable接口,确实是帮助我们达到了对任意对象数组实现排序,但是依然是不够灵活的,因为总要

去各个类里实现Comparable接口,耦合度比较高。例如,我要换一种排序规则呢?比如猫之前是按照体重排序,我现在

想要按照身高排序该怎么办?直接改接口实现非常不灵活。说白了,我想要猫的比较大小的策略可以灵活指定,该怎么实现?

这时候策略模式隆重登场啦。我们要知道,在设计的指导思想里边,有一个非常重要的概念,对扩展开放,对修改关闭

Comparator接口

package org.ali.strategy;

/**
 * Author: lury
 * Date: 2022-09-04 12:44
 */
public interface Comparator<T> {
    int compare(T o1,T o2);
}
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[i]) == -1 ? j : minPos;
            }

            swap(arr,i,minPos);
        }
    }
  }

测试

package org.ali.strategy;

import java.util.Arrays;

/**
 * Author: lury
 * Date: 2022-09-04 11:08
 */
public class Main {
    public static void main(String[] args) {
        Cat[] cats = {new Cat(4,7),new Cat(3,4)};
        Dog[] dogs = {new Dog(2),new Dog(4)};

        new Sorter<Cat>().sort(cats,((o1, o2) ->
            o1.height - o2.height < 0 ? -1 : 1
        ));

        System.out.println(Arrays.toString(cats));

    }
}

image-20220904132019234

神奇吧?怎么做到的,就是在需要灵活变换的比较方法中,多加一个接口,把接口的实现留白给用户实现

类图

![image-20220904133157807](D:\Download\尚硅谷\msb\designer pattern\img\image-20220904133157807.png)

说白了就是 对策略进行开放拓展,排序的话,就可以有很多种策略

实际怎么运用?去代替if

posted on 2022-09-04 13:46  万能包哥  阅读(24)  评论(0编辑  收藏  举报