策略设计模式Strategy
- Comparable 是被比较对象和比较策略没有解耦
- Comparator 是被比较对象和比较策略解耦了,在真正要比较的时候才会定义比较策略。这就是策略模式****(实现比较策略和被比较对象的解耦)
相比于策略模式,非策略模式不符合开闭原则,比如Comparable想要修改比较方法,必须修改实现类的内部。而使用了策略模式的Comparator就不需要
详细版
业务逻辑可能有很多方式都可以实现某个具体的功能。例如,按照购买次数对一个用户购买的全部商品进行排序,从而粗略地得知该用户复购率最高的商品,我们可以使用多种排序算法来实现这个功能,例如,归并排序、插入排序、选择排序等。
- 之前都是if else,新增的时候直接追加
- 在策略模式中,我们会将每个算法单独封装成不同的算法实现类(这些算法实现类都实现了相同的接口),每个算法实现类就可以被认为是一种策略实现,我们只需选择不同的策略实现来解决业务问题即可,这样每种算法相对独立,算法内的变化边界也就明确了,新增或减少算法实现也不会影响其他算法。
StrategyUser 是算法的调用方,维护了一个 Strategy 对象的引用,用来选择具体的算法实现。

应用
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) 收藏 举报
浙公网安备 33010602011771号