在JDK中,你能找到哪些策略模式的实际应用案例?请举例说明。
参考回答
问题:在JDK中,你能找到哪些策略模式的实际应用案例?请举例说明。
在JDK中,有很多地方都运用了策略模式,尤其是在集合框架和排序等场景中。最常见的应用案例包括Comparator接口的使用和Collections.sort()方法。
详细讲解与拓展
1. Comparator和Collections.sort()
Comparator接口和Collections.sort()方法是JDK中典型的策略模式应用。Comparator用于定义排序算法,而Collections.sort()方法通过传入不同的Comparator对象来实现灵活的排序策略切换。
具体应用:
- 策略接口:
Comparator接口,它定义了一个compare()方法,用于比较两个对象的大小。 - 具体策略类:实现
Comparator接口的具体类(例如:Comparator<Integer>、Comparator<String>等),每个策略类实现不同的比较方式。 - 上下文类:
Collections.sort()方法,作为上下文类,它接收一个Comparator对象,并通过调用该对象的compare()方法来对集合进行排序。
代码示例:
import java.util.*;
public class StrategyPatternInJDK {
public static void main(String[] args) {
List<Integer> numbers = Arrays.asList(5, 3, 7, 1, 9, 2);
// 按升序排序
Collections.sort(numbers, new Comparator<Integer>() {
@Override
public int compare(Integer o1, Integer o2) {
return o1 - o2; // 升序
}
});
System.out.println("升序排序: " + numbers);
// 按降序排序
Collections.sort(numbers, new Comparator<Integer>() {
@Override
public int compare(Integer o1, Integer o2) {
return o2 - o1; // 降序
}
});
System.out.println("降序排序: " + numbers);
}
}
工作原理:
Comparator是策略模式中的策略接口,它定义了比较算法(即排序规则)。Collections.sort()方法充当上下文类,根据传入的Comparator对象执行不同的排序策略。- 当我们传入不同的
Comparator实现时,Collections.sort()就会按不同的方式进行排序。这使得排序行为是可配置的,并且可以在运行时灵活切换。
2. ThreadPoolExecutor的策略模式应用
ThreadPoolExecutor类中的RejectedExecutionHandler接口也是策略模式的一个应用。在ThreadPoolExecutor中,当线程池中的任务队列已满,无法接受新的任务时,它会通过RejectedExecutionHandler接口的实现来处理被拒绝的任务。
具体应用:
- 策略接口:
RejectedExecutionHandler接口,用于定义当任务被拒绝时的处理策略。 - 具体策略类:例如,
AbortPolicy(抛出异常)、CallerRunsPolicy(由提交任务的线程自己执行任务)等。 - 上下文类:
ThreadPoolExecutor类,根据具体的拒绝策略执行不同的任务拒绝处理方式。
代码示例:
import java.util.concurrent.*;
public class ThreadPoolExecutorStrategyExample {
public static void main(String[] args) {
// 创建一个核心线程数为2,最大线程数为4,任务队列大小为2的线程池
ThreadPoolExecutor executor = new ThreadPoolExecutor(2, 4, 60, TimeUnit.SECONDS,
new ArrayBlockingQueue<>(2), new ThreadPoolExecutor.AbortPolicy()); // 使用AbortPolicy策略
for (int i = 0; i < 6; i++) {
final int taskId = i;
executor.submit(() -> {
System.out.println("Executing task " + taskId);
});
}
executor.shutdown();
}
}
工作原理:
RejectedExecutionHandler是一个策略接口,定义了当线程池任务被拒绝时的处理方式。ThreadPoolExecutor通过传入不同的RejectedExecutionHandler策略来决定如何处理拒绝的任务。- 例如,
AbortPolicy策略会直接抛出RejectedExecutionException异常,而CallerRunsPolicy策略则会让提交任务的线程自己去执行该任务。
3. java.util.stream中的Collector
在Java 8的Stream API中,Collector接口也是策略模式的一种应用。Collector用于定义如何将流中的元素累积成一个结果(比如:List、Set、Map、String等)。
具体应用:
- 策略接口:
Collector接口,定义了如何对流中的元素进行收集。 - 具体策略类:例如:
Collectors.toList()、Collectors.joining()、Collectors.groupingBy()等。 - 上下文类:
Stream.collect()方法,根据传入的Collector实现来对流中的元素进行不同的操作(例如:收集成一个List,或将元素拼接成一个String)。
代码示例:
import java.util.*;
import java.util.stream.*;
public class StreamCollectorStrategyExample {
public static void main(String[] args) {
List<String> names = Arrays.asList("Alice", "Bob", "Charlie", "David");
// 使用不同的策略(Collector)收集流中的元素
List<String> list = names.stream()
.collect(Collectors.toList()); // 使用toList策略
System.out.println("List: " + list);
String result = names.stream()
.collect(Collectors.joining(", ")); // 使用joining策略
System.out.println("Joined: " + result);
Map<Integer, List<String>> grouped = names.stream()
.collect(Collectors.groupingBy(String::length)); // 使用groupingBy策略
System.out.println("Grouped: " + grouped);
}
}
工作原理:
Collector接口定义了如何对流中的元素进行累积操作。Stream.collect()方法根据传入的Collector实现来进行不同的收集操作(如将元素收集到List、Map,或将字符串连接成一个大字符串等)。- 这种方式符合策略模式的思想,策略(即收集方法)被封装在
Collector对象中,Stream通过调用collect()方法灵活地使用不同的策略来处理流中的元素。
总结
在JDK中,策略模式的应用非常广泛,尤其是在集合类、线程池、流操作等方面。通过策略模式,JDK能够为开发者提供灵活的操作方式,不同的策略(算法或行为)可以在运行时进行选择和切换,增强了系统的可扩展性和灵活性。例如,Comparator接口用于排序的策略、ThreadPoolExecutor中的拒绝策略以及Stream中的收集策略,都是策略模式的实际应用案例。