Reference from the horse soldier design pattern source

Gitee link

My understanding is that different objects have different processing strategies

For example, there is a sorting utility class Sorter, which sorts the array passed in, like this:

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

            for (int j = i+1; j < arr.length; j++) {
                minPos = arr[j] < arr[minPos] == -1? j : minPos; } swap(arr, i, minPos); }}private static void swap(int[] arr, int i, int minPos) {
        inttemp = arr[i]; arr[i] = arr[minPos]; arr[minPos] = temp; }}Copy the code

One problem with this sorting utility class is that it only supports int arrays, not objects, etc., so let’s use the policy mode step by step.

Start by creating two new classes Cat and Dog for testing:

package com.cc.strategy;

public class Cat {
    int weight, height;

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

    @Override
    public String toString(a) {
        return "Cat{" +
                "weight=" + weight +
                ", height=" + height +
                '} '; }}Copy the code
package com.cc.strategy;

public class Dog {
    int food;

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

    @Override
    public String toString(a) {
        return "Dog{" +
                "food=" + food +
                '} '; }}Copy the code

Cat has two attributes, weight and height, and Dog has one food.

First we want the Sorter class to do this, sort the Cat array by weight, so we can write:

Create a new implementation class Comparable (I know Java already has this implementation class, but for better understanding, let’s manually create one) :

package com.cc.strategy;

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

Where the generic T can be confusing, as WE’ll see later,

To support Sorter sorting, Cat needs to implement the Comparable class as follows:

package com.cc.strategy2;

// The generics mentioned above can be specified here...
public class Cat implements Comparable<Cat> {
    int weight, height;

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

    / * * *... Object o => Cat c * If you don't use generics, you write one more line like this: * Cat c = (Cat)o; * /
    @Override
    public int compareTo(Cat c) {
        if (this.weight < c.weight) {
            return -1;
        } else if (this.weight > c.weight) {
            return 1;
        } else {
            return 0; }}@Override
    public String toString(a) {
        return "Cat{" +
                "weight=" + weight +
                ", height=" + height +
                '} '; }}Copy the code

The Sorter class will also be changed from accepting only int[] to Comparable[], i.e., all objects that have achieved Comparable:

package com.cc.strategy2;

public class Sorter {
    public void sort(Comparable[] arr) {
        for (int i = 0; i < arr.length; 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); }}private void swap(Comparable[] arr, int i, int minPos) { Comparable temp = arr[i]; arr[i] = arr[minPos]; arr[minPos] = temp; }}Copy the code

Test it out;

package com.cc.strategy;

import java.util.Arrays;

public class Main {
    public static void main(String[] args) {
        Cat[] c = {new Cat(3.3), new Cat(5.5), new Cat(1.1)};
        Sorter sorter = newSorter(); sorter.sort(c); System.out.println(Arrays.toString(c)); }}Copy the code

Results:

[Cat{weight=1, height=1}, Cat{weight=3, height=3}, Cat{weight=5, height=5}]
Copy the code

Now that we have sorted the Cat class, when we want to sort Dog, we can use the Cat class:

package com.cc.strategy;

public class Dog implements Comparable<Dog> {
    int food;

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

    @Override
    public int compareTo(Dog d) {
        if (this.food < d.food) {
            return -1;
        } else if (this.food > d.food) {
            return 1;
        } else {
            return 0; }}@Override
    public String toString(a) {
        return "Dog{" +
                "food=" + food +
                '} '; }}Copy the code

CompareTo () : compareTo() : compareTo() : compareTo() : compareTo() : compareTo() : compareTo(); You can’t change the implementation function compareTo(). It’s not flexible at all. Now it’s the policy mode.

Let’s create a new comparison implementation class Comparator:

package com.cc.strategy;

public interface Comparator<T> {
    int comare(T o1, T o2);
}
Copy the code

Now, what’s the difference between this Comparator and Comparable?

A: In Java, Comparable is a sort interface. If a class implements Comparable, that class supports sorting, as we did in Sorter. Objects that implement Comparable are sorted using the compareTo() method, which returns 1, -1, or 0.

A Comparator is a comparison interface, which is usually used to implement a comparison method.


In order to be flexible, we can sort Cat by weight or height. We create two new comparison classes:

package com.cc.strategy;

public class CatHeightComparator implements Comparator<Cat> {
    @Override
    public int comare(Cat o1, Cat o2) {
        if (o1.height < o2.height) {
            return 1;
        } else if (o1.height > o2.height) {
            return -1;
        } else {
            return 0; }}}Copy the code
package com.cc.strategy;

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

Compare (); compare(); compare();

package com.cc.strategy;

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

            for (int j = i+1; j < arr.length; j++) {
                minPos = comparator.comare(arr[j], arr[minPos]) == -1? j : minPos; } swap(arr, i, minPos); }}private void swap(T[] arr, int i, int minPos) { T temp = arr[i]; arr[i] = arr[minPos]; arr[minPos] = temp; }}Copy the code

Now we can delete the Cat code for the Comparable implementation class and leave a clean object, because the sorting implementation is placed in the CatHeightComparator and CatWeightComparator:

package com.cc.strategy;

public class Cat {
    int weight, height;

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

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

Test it out:

package com.cc.strategy;

import java.util.Arrays;

public class Main {
    public static void main(String[] args) {
        Cat[] c = {new Cat(3.3), new Cat(5.5), new Cat(1.1)};

        Sorter<Cat> catSorter = new Sorter<>();

        catSorter.sort(c, new CatWeightComparator());
        System.out.println(Arrays.toString(c));
        
        catSorter.sort(c, newCatHeightComparator()); System.out.println(Arrays.toString(c)); }}Copy the code

Results:

[Cat{weight=1, height=1}, Cat{weight=3, height=3}, Cat{weight=5, height=5}]
[Cat{weight=5, height=5}, Cat{weight=3, height=3}, Cat{weight=1, height=1}]
Copy the code

Congrats, Sorter sort class can the incoming object array, according to the different sorting strategy for different sort, this is the strategy pattern of use, although the code a little more, but the maintenance is very high, when we want to the Dog class or more classes for sorting operation, only need to create a new sorting strategy.