策略设计模式Strategy

  • Comparable 是被比较对象和比较策略没有解耦
  • Comparator 是被比较对象和比较策略解耦了,在真正要比较的时候才会定义比较策略。这就是策略模式****(实现比较策略和被比较对象的解耦)

相比于策略模式,非策略模式不符合开闭原则,比如Comparable想要修改比较方法,必须修改实现类的内部。而使用了策略模式的Comparator就不需要

详细版

业务逻辑可能有很多方式都可以实现某个具体的功能。例如,按照购买次数对一个用户购买的全部商品进行排序,从而粗略地得知该用户复购率最高的商品,我们可以使用多种排序算法来实现这个功能,例如,归并排序、插入排序、选择排序等。

  • 之前都是if else,新增的时候直接追加
  • 在策略模式中,我们会将每个算法单独封装成不同的算法实现类(这些算法实现类都实现了相同的接口),每个算法实现类就可以被认为是一种策略实现,我们只需选择不同的策略实现来解决业务问题即可,这样每种算法相对独立,算法内的变化边界也就明确了,新增或减少算法实现也不会影响其他算法。

StrategyUser 是算法的调用方,维护了一个 Strategy 对象的引用,用来选择具体的算法实现。

1622889959548-778e13a4-20d1-4bd5-b2fc-c4e5a55f8a8f.png

应用

java.lang.Comparable 不是,他的方法还是写死在类里面的,因为参数只有一个,所以必须有当前对象的引用

java.util.Comparator 是策略模式,有两个参数,他的方法不是写死在类的,需要单独传递比较器在需要对类比较的时候随时定义。实现子类表达怎么比较两个类的大小

上面两个都使用了泛型。是为了扩展性,但是在实现的时候记得标明,不然使用实体类的时候就需要强转换。

lamda表达式就会使用这个,函数式接口注意是必须有default方法的,default就是为了兼容之前的版本,不让之前的已有版本重构,又让这个接口支持了lamda表达式

java.util.Comparator就是策略模式

匿名内部类做参数传递过去,其实接收的方法里面只是调用了接口的方法,具体的实现类不管,调用者只是面向接口编写,这就是策略设计模式

非策略模式演示

比较的方法写死在了实体类里面,想要比较其他的属性的时候需要修改源代码,违背了开闭原则对修改关闭

定义类似Comparable 的接口

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

定义实现了接口的实体类,里面直接定义唯一的比较方法

注意实现接口的时候,要指定泛型的类型,否则比较的时候需要将对象强制转换才可以使用类中自己的属性

package com.deltaqin.designPattern.d02_strategy;

import lombok.Data;

/**
 * @author deltaqin
 * @date 2021/3/26 2:39 下午
 */
@Data
public class Cat implements Comparable<Cat>{
    int height;
    int weight;

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

    public int compareTo(Cat o) {
        if (height < o.height)
            return -1;
        else if (height > o.height)
            return 1;
        else
            return 0;
    }
}

面向接口调用比较的方式

注意参数的类型直接就是Comparable,不是泛型,这样才可以直接使用它的compareTo方法

package com.deltaqin.designPattern.d02_strategy;

import java.util.Arrays;
import java.util.Comparator;

/**
 * @author deltaqin
 * @date 2021/3/26 2:31 下午
 */
// 使用泛型,配合比较策略,直接调用策略的接口方法,
//     具体的策略由使用者使用的时候传入,而不是定义具体类的时候,类和策略应该是分离的
public class Sorter {
    public void sort(Comparable[] arr) {
        for (int i = 0; i < arr.length -1; i++) {
            int min = i;
            for (int j = i+1; j < arr.length; j++) {
                if (arr[j].compareTo(arr[min]) == -1 )
                    min = j;
            }
            swap1(arr, min, i);
        }

        System.out.println(Arrays.toString(arr));
    }

    public  void swap1(Comparable[] arr, int i, int j) {
        Comparable t = arr[i];
        arr[i] = arr[j];
        arr[j] = t;
    }
}

package com.deltaqin.designPattern.d02_strategy;

import java.util.Arrays;

/**
 * @author deltaqin
 * @date 2021/3/26 2:39 下午
 */
public class Main {
    public static void main(String[] args) {
        // 不使用策略模式
        // 在Cat 或者 Dog 里面写死比较方法,也就是只可以有一种比较方法
        Cat[] cats = new Cat[] {
                new Cat(12,12),
                new Cat(11,11),
                new Cat(14,14)
        };

        Sorter sorter = new Sorter();
        sorter.sort(cats);
        System.out.println(Arrays.toString(cats));
    }
}

实现案例--策略模式

定义比较策略

函数式接口,

package com.deltaqin.designPattern.d02_strategy;

/**
 * @author deltaqin
 * @date 2021/3/26 3:38 下午
 */
@FunctionalInterface
public interface Comparator<T> {
    public int compare(T o1, T o2);
}

定义策略的使用者

package com.deltaqin.designPattern.d02_strategy;

import java.util.Arrays;
import java.util.Comparator;

/**
 * @author deltaqin
 * @date 2021/3/26 2:31 下午
 */
// 使用泛型,配合比较策略,直接调用策略的接口方法,
//     具体的策略由使用者使用的时候传入,而不是定义具体类的时候,类和策略应该是分离的
public class Sorter<T> {

    // 选择
    public void sort(T[] arr, Comparator<T> comparator) {
        for (int i = 0; i < arr.length -1; i++) {
            int min = i;
            for (int j = i+1; j < arr.length; j++) {
                if (comparator.compare(arr[j] , arr[min]) == -1 )
                    min = j;
            }
            swap(arr, min, i);
        }

        System.out.println(Arrays.toString(arr));
    }

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

定义实体类

不需要实现任何的比较方法,在这里实现就写死了

@Data
public class Cat{
    int height;
    int weight;

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

现场编写比较实体类的某个属性的方法

实现比较策略的接口,定义比较的规则,按照策略的规则返回结果,因为内部调用的时候也是按照这个规则来调用的。

package com.deltaqin.designPattern.d02_strategy;

import java.util.Arrays;

/**
 * @author deltaqin
 * @date 2021/3/26 2:39 下午
 */
public class Main {
    public static void main(String[] args) {
        // 不使用策略模式
        // 在Cat 或者 Dog 里面写死比较方法,也就是只可以有一种比较方法
        Cat[] cats = new Cat[] {
                new Cat(12,12),
                new Cat(11,11),
                new Cat(14,14)
        };

        //Sorter sorter = new Sorter();
        //sorter.sort(cats);
        //System.out.println(Arrays.toString(cats));


        // 使用策略模式
        // 在使用的时候定义比较的策略,按照固定的要求结果写自己的比较策略
        Sorter<Cat> sorter1 = new Sorter();
        sorter1.sort(cats, (o1, o2)-> {
            if (o1.height < o2.height)
                return -1;
            else if (o1.height > o2.height)
                return 1;
            else
                return 0;
        });
        System.out.println(Arrays.toString(cats));
    }
}

策略和工厂的区别

策略是对方法的抽象,关注的是脱离出具体接口的一个通用策略方法。只是说一个用来比较的工具(策略),至于具体的策略实现要和被比较对象解耦,在真正使用的时候才会创建规则。

是很多对象都需要的方法,抽象出来,供外界在没有具体实现的可以面向接口编程

工厂注重的是对象自己的划分,为了实现对象自己的可重用和可扩展

posted on 2025-10-14 23:00  chuchengzhi  阅读(6)  评论(0)    收藏  举报

导航

杭州技术博主,专注分享云计算领域实战经验、技术教程与行业洞察, 打造聚焦云计算技术的垂直博客,助力开发者快速掌握云服务核心能力。

褚成志 云计算 技术博客