如何在Java中使用策略模式?
大家好,你可能听说过,“你能告诉我你最近在你的项目中使用的除了单例设计模式之外的任何设计模式吗?”。 这是近年来各种Java面试的热门问题之一。 我认为这实际上激励了许多 Java 程序员探索更多的设计模式,并实际查看 GOF 引入的原始 23 种模式。 策略设计模式是我们在回答此类问题时可以提及的有用模式之一。 它非常流行,并且在许多真实场景中,策略模式非常方便。
学习设计模式的最佳方法是什么,首先需要了解其他人如何使用它们,为此,需要查看我们在日常任务中使用的开源库。 JDK API 是我每天使用的一个这样的库,这就是为什么当我探索新的算法、设计模式时,我首先搜索 JDK 以了解它们的用法。
策略模式在 JDK 中找到了它的位置,如果你在 Java 中对 ArrayList
进行过排序,你就会明白。 是的,Comparator、Comparable
和 Collections.sort()
方法的组合是策略设计模式的最佳现实示例之一。
为了更深入地理解它,我们先来了解一下什么是策略模式? 第一条线索是名字本身。 策略模式定义了一系列相关算法,像排序算法,如冒泡排序、快速排序、插入排序和归并排序,或压缩算法,如 zip 、gzip 、tar 、jar,加密算法,如 MD5 、AES 等,并让算法 独立于使用它的用户。
例如,我们可以使用策略模式来实现一种对数字进行排序的方法,并允许客户端在运行时选择任何排序算法,而无需修改客户端的代码。 所以本质上,策略模式提供了灵活性、可扩展性和选择。 当我们需要在运行时选择算法时,我们应该考虑使用这种模式。
在 Java 中,策略通常是通过创建从称为 Strategy
的基接口扩展的类的层次结构来实现的。 在本教程中,我们将通过编写 Java 程序并演示它如何为我们的代码增加价值来学习有关策略模式的一些有趣的事情。
Java策略设计模式终极指南
现在,让我们深入了解策略设计模式。 我已经介绍了什么是策略设计模式、它提供的好处、在哪里使用策略模式以及如何在 Java 中实现策略设计模式。
我们还将看到一些策略设计模式的真实示例,特别是来自 JDK 和其他流行的开源库的示例,以深入了解策略设计模式的意图。 阅读本文后,大家应该有信心在自己的 Java 项目和程序中使用策略设计模式。
1. 策略设计模式的意图是什么?
在学习新模式时,最重要的是要理解意图和动机。 为什么? 因为两个设计模式可以具有相同的结构,但它们的意图可能完全不同。该理论的一个很好的例子是状态和策略模式。
如果查看这两种模式的 UML
图,它们看起来是相同的,但状态模式的目的是促进状态转换,而策略模式的目的是通过在运行时更改内部算法而不修改类的行为来改变类的行为 。 这就是为什么策略模式是 GOF 原始列表中行为模式的一部分。
我们可以将策略模式与人们如何使用不同的策略来处理不同的情况相关联,例如,如果我们遇到一种情况,那么我们要么处理它,要么使用两种不同的策略避免它。
2. 策略模式的术语和结构
该模式有两个主要组件,Strategy
接口和 Context
类。 Strategy
接口声明了算法的类型,可以是抽象类或接口。 例如,你可以定义一个带有方法 move()
的 Strategy
接口,现在这一步就变成了策略,一盘棋中的不同棋子可以实现这个方法来定义他们的移动策略。
例如
,Rook
只能水平或垂直移动,Bishop
将沿对角线移动,Pawn
一次移动一个格子,Queen
可以水平、垂直和对角线移动。 不同棋子移动所采用的不同策略是Strategy
接口的实现,移动棋子的代码是我们的Context
类。
当我们改变一块时,我们不需要改变上下文类。 如果添加了一个新的片段,那么你的负责移动片段的代码也不需要修改。
这是策略模式的 UML 图:
3. 策略模式的优缺点
每种算法或模式都有优点和缺点,这种模式也不例外。 使用策略模式的主要好处是灵活性。 客户端可以在运行时选择任何算法,我们可以轻松添加新的策略而无需修改 Context
等使用策略的类。
这之所以成为可能,是因为策略模式基于开放封闭设计原则,即通过编写新代码而不是通过修改久经考验的旧代码来添加新行为。
如果我们使用策略模式,我们将通过编写一个只需要实现 Strategy
接口的新类来添加一个新的策略。 因为违反了开闭原则,我们不能用枚举来实现策略模式。
虽然它有一些优点并且很适合如果我们提前了解主要算法但我们需要修改 Enum 类以添加新算法,这违反了开闭原则。
4. 策略设计模式的真实例子
JDK 有几个这种模式的例子,第一个是 Collection.sort(List, Comparator)
方法,其中 Comparator
是 Strategy,Collections.sort()
是 Context。 由于这种模式,我们的排序方法可以对任何对象进行排序,该对象在编写此方法时不存在。
只要,Object 会实现 Comparator
接口(Strategy 接口),Collections.sort()
方法就会对其进行排序。
另一个例子是 java.util.Arrays#sort(T[], Comparator < ? super T > c)
方法,它类似于 Collections.sort()
方法,只是需要用数组代替 List。
5. Java中策略模式的实现
这是一个实现策略设计模式的简单 Java 程序。 我们可以使用此示例代码来学习和试验此模式。 这个例子非常简单,它所做的就是为排序算法定义一个策略接口,并在一个名为 arrange 的方法上使用该接口。
此方法可以按升序或降序排列对象,具体取决于我们如何实现它们。 为了安排一个对象,我们需要排序,这是由策略模式提供的。 这允许我们选择任何算法来对我们的对象进行排序。
public class Test {
public static void main(String args[]) throws InterruptedException {
// we can provide any strategy to do the sorting
int[] var = {1, 2, 3, 4, 5 };
Context ctx = new Context(new BubbleSort());
ctx.arrange(var);
// we can change the strategy without changing Context class
ctx = new Context(new QuickSort());
ctx.arrange(var);
}
}
interface Strategy {
public void sort(int[] numbers);
}
class BubbleSort implements Strategy {
@Override
public void sort(int[] numbers) {
System.out.println("sorting array using bubble sort strategy");
}
}
class InsertionSort implements Strategy {
@Override
public void sort(int[] numbers) {
System.out.println("sorting array using insertion sort strategy");
}
}
class QuickSort implements Strategy {
@Override
public void sort(int[] numbers) {
System.out.println("sorting array using quick sort strategy");
}
}
class MergeSort implements Strategy {
@Override
public void sort(int[] numbers) {
System.out.println("sorting array using merge sort strategy");
}
}
class Context {
private final Strategy strategy;
public Context(Strategy strategy) {
this.strategy = strategy;
}
public void arrange(int[] input) {
strategy.sort(input);
}
}
上述代码输出结果如下
sorting array using bubble sort strategy
sorting array using quick sort strategy
6. 关于 Java 中策略模式的注意事项
现在让我们复习一下在本篇文章中学到的有关策略模式的知识:
- 该模式定义了一组相关的算法并将它们封装在单独的类中,并允许客户端在运行时选择任何算法。
- 它允许在不修改现有算法或使用算法或策略的上下文类的情况下添加新算法。
- 策略是GOF列表中的一种行为模式。
- 策略模式基于SOLID Principles of Object-Oriented Design的开闭设计原则。
-
Collections.sort()
和 Comparator 接口是策略模式的真实示例。
这就是关于如何在 Java 中实现策略模式的全部内容。
相关文章
使用 Java 在 MongoDB 中生成 ObjectId
发布时间:2023/04/20 浏览次数:179 分类:MongoDB
-
本文将讨论 ObjectId 以及我们如何使用 Java 程序生成它。 为了使主题更简单,我们将看到一个带有解释的示例,以使主题更容易。
在 PHP 变量中存储 Div Id 并将其传递给 JavaScript
发布时间:2023/03/29 浏览次数:69 分类:PHP
-
本文教导将 div id 存储在 PHP 变量中并将其传递给 JavaScript 代码。
如何在 Java 中把日期转换为字符串
发布时间:2023/03/28 浏览次数:192 分类:Java
-
本篇文章介绍了如何在 Java 中把 java.util.Date 转换为字符串 String。