设计模式——策略模式

所有源码的git地址https://gitee.com/0x208_jackson/design-patterns

1、设计模式该怎么用

​ 当我们项目中出现了多个if……else的时候就可以选择使用策略模式,策略模式就是做同一件事件的不同的方法,设计模式说到底就是java多态的灵活运用。设计项目时我们一般要遵循开闭原则,即关闭修改,打开扩展,也就是说尽量别去修改现有的代码,而是对其进行扩展,这就要求我们在设计的时候需要考虑到可以进行灵活的扩展。

2、策略模式-比较动物大小

2.1、根据体重比较

我们现在有一只猫,根据体重比较猫的大小,代码如下:

猫的实体对象

package com.xin.demo.strategy;

import java.io.Serializable;

public class Cat implements Serializable {
    private final int weight;
    private final int height;

    public int compareToHeight(Cat cat) {
        return this.weight - cat.weight;
    }

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

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

排序:

package com.xin.demo.strategy;

public class Sort {
    // 此处通过 采用选择排序进行排序
    public static void selectionSort(Cat[] arr) {
        if (arr == null || arr.length < 2) {
            return;
        }
        for (int i = 0; i < arr.length - 1; i++) {
            int minIndex = i;
            for (int j = i + 1; j < arr.length; j++) {
              // 此处是重点需要注意,注意看调用的方法名
              // 此处需要根据 不同的比较方式去调用不同的方法,也就是会产生多个if……else
              minIndex = arr[j].compareToHeight(arr[minIndex]) < 0 ? j : minIndex;
            }
            swap(arr, i, minIndex);
        }
    }

    public static void swap(Cat[] arr, int i, int j) {
        Cat tmp = arr[i];
        arr[i] = arr[j];
        arr[j] = tmp;
    }

}

执行:

package com.xin.demo.strategy;

import java.util.Arrays;

public class OperatorMain {
    public static void main(String[] args) {
        Cat[] a = {new Cat(23, 2),
                new Cat(14, 11),
                new Cat(5, 7),
                new Cat(1, 1)};
        Sort.selectionSort(a);
        System.out.println(Arrays.toString(a));
    }
}
2.2、根据身高比较

现在我希望根据猫的身高比较猫的大小,按照常规写法,我们需要在 Cat 对象里面在实现一个方法.

package com.xin.demo.strategy;

import java.io.Serializable;

public class Cat implements Serializable {
    private final int weight;
    private final int height;
  
    public int compareToHeight(Cat cat) {
        return this.weight - cat.weight;
    }

    // 此处为新增加的 根据体重进行比较的方法
    public int compareToWeight(Cat cat) {
        return this.weight - cat.weight;
    }

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

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

修改排序的调用方法

package com.xin.demo.strategy;

public class Sort {
    // 此处通过 采用选择排序进行排序
    public static void selectionSort(Cat[] arr) {
        if (arr == null || arr.length < 2) {
            return;
        }
        for (int i = 0; i < arr.length - 1; i++) {
            int minIndex = i;
            for (int j = i + 1; j < arr.length; j++) {
            // 注意此处改成了 调用体重的方法
            // 此处需要根据 不同的比较方式去调用不同的方法,也就是会产生多个if……else
 							minIndex = arr[j].compareToWeight(arr[minIndex]) < 0 ? j : minIndex;
            }
            swap(arr, i, minIndex);
        }
    }

    public static void swap(Cat[] arr, int i, int j) {
        Cat tmp = arr[i];
        arr[i] = arr[j];
        arr[j] = tmp;
    }

}

2.3、根据策略模式

​ 以上两种情况我们发现,如果在做同一件猫的大小的比较,根据不同的方式去做的时候我们需要写很多冗余的代码,且不利于扩展,如在增加一种比较方式的时候,我们需要继续进行方法的迭代,且排序方法需要在增加或者重写,此处策略主要针对的是排序部分。

​ 既然是同一件事情,不同的方式去做,那么我们可以定义一个比较器接口,通过不同的实现来完成。

首先定义一个接口:

package com.xin.demo.strategy;

public interface Comparator<T> {

    // 比较器
    int compare(T o1, T o2);
}

对应的实现:

体重:

package com.xin.demo.strategy;

public class CatCompareToHeight implements Comparator<Cat> {
    @Override
    public int compare(Cat o1, Cat o2) {
        return o1.height - o2.height;
    }
}

身高:

package com.xin.demo.strategy;

public class CatCompareToWeight implements Comparator<Cat> {
    @Override
    public int compare(Cat o1, Cat o2) {
        return o1.weight - o2.weight;
    }
}

排序方法:

package com.xin.demo.strategy;

public class StrategySort<T> {
    // 此处通过 采用选择排序进行排序
    public void selectionSort(T[] arr, Comparator<T> comparator) {
        if (arr == null || arr.length < 2) {
            return;
        }
        for (int i = 0; i < arr.length - 1; i++) {
            int minIndex = i;
            for (int j = i + 1; j < arr.length; j++) {
              // 重点
                minIndex = comparator.compare(arr[j], arr[minIndex]) < 0 ? j : minIndex;
            }
            swap(arr, i, minIndex);
        }
    }

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

}

执行:

package com.xin.demo.strategy;

import java.util.Arrays;

public class OperatorMain {
    public static void main(String[] args) {

        Cat[] cat = {new Cat(3, 4),
                new Cat(14, 11),
                new Cat(5, 17),
                new Cat(1, 2)};
        // 普通写法
        Sort.selectionSort(cat);
        System.out.println(Arrays.toString(cat));

        // 策略模式写法
        StrategySort<Cat> strategySort = new StrategySort<>();
        // 传进去需要比较的对象,以及对应的策略,也就是对应的比较方式
        // 根据身高比较
        strategySort.selectionSort(cat, new CatCompareToHeight());
        System.out.println("根据height排序:"+Arrays.toString(cat));

        //根据体重进行比较
        strategySort.selectionSort(cat, new CatCompareToWeight());
        System.out.println("根据weight排序:"+Arrays.toString(cat));

    }
}

2.4、可以比较任何动物的大小
package com.xin.demo.strategy;

import java.util.Arrays;

public class OperatorMain {
    public static void main(String[] args) {
        // 现在我们不仅可以比较猫的大小,还可以比较任何一个动物的大小
        // lambda 表达式写法
        StrategySort<Dog> dogStrategySort = new StrategySort<>();
        Dog[] dogs = {new Dog(3, 9),
                new Dog(1, 11),
                new Dog(4, 1),
                new Dog(2, 2)};
        dogStrategySort.selectionSort(dogs, new Comparator<Dog>() {
            @Override
            public int compare(Dog o1, Dog o2) {
                return o1.height - o2.height;
            }
        });
        System.out.println(Arrays.toString(dogs));
    }
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值