文章目录
- 一、前言
- 二、知识点构成
- 三、总结
一、前言
在软件设计中,我们经常会面临需要根据不同情况选择不同算法或方法的问题。这些情况可能是基于不同的输入、不同的需求或不同的环境。策略模式(Strategy Pattern)是一种行为型设计模式,它能够让我们以一种优雅的方式在运行时选择算法,从而提高代码的灵活性和可维护性。
二、知识点构成
1、策略模式介绍
策略模式定义了算法家族,分别封装起来,让它们之间可以互相替换,此模式让算法的变化不会影响到使用算法的客户。
2、理解策略模式
策略模式的核心思想是将不同的算法封装成独立的类,并且使这些类可以互相替换。这样,我们可以在运行时根据需要动态地切换算法,而不需要修改调用算法的代码。策略模式主要由三个角色组成:
2.1、策略接口(Strategy Interface)
定义了具体策略类(算法类)必须实现的方法,确保所有策略类都具有相同的行为约定。
java
interface SortingStrategy {
void sort(int[] array);
}
2.2、具体策略类(Concrete Strategies)
实现了策略接口,封装了具体的算法逻辑。
java
class BubbleSort implements SortingStrategy {
@Override
public void sort(int[] array) {
// 实现冒泡排序算法
}
}
class QuickSort implements SortingStrategy {
@Override
public void sort(int[] array) {
// 实现快速排序算法
}
}
2.3、上下文类(Context)
持有一个策略对象,并在运行时根据需要调用具体的策略,将算法的选择和使用与客户端代码解耦。
java
class Sorter {
private SortingStrategy strategy;
public void setStrategy(SortingStrategy strategy) {
this.strategy = strategy;
}
public void performSort(int[] array) {
strategy.sort(array);
}
}
2.4、客户端使用
java
public class Main {
public static void main(String[] args) {
int[] data = {5, 2, 8, 1, 3};
Sorter sorter = new Sorter();
sorter.setStrategy(new BubbleSort());
sorter.performSort(data);
// 或者切换到另一个策略
sorter.setStrategy(new QuickSort());
sorter.performSort(data);
}
}
3、优点与应用
策略模式的优点在于它能够将不同算法的实现与调用代码分离,使得代码更易于理解、扩展和维护。它适用于以下场景:
- 当有多种算法可以选择时,通过策略模式可以避免使用复杂的条件语句。
- 当一个类有多个行为变体,而这些变体经常需要在运行时切换时,策略模式是一个好的选择。
- 当需要在不同的上下文中使用不同的算法时,策略模式可以让算法与上下文独立变化,互不影响。
4、策略模式的优化
当你新增一个算法策略子类时,客户端的代码需要进行修改,这违反了开闭原则。开闭原则要求软件实体(类、模块、函数等)应该是可扩展的,而不需要修改已有的代码。但是在实际情况中,新增策略可能需要客户端代码进行相应的调整,因为你需要告诉上下文类应该使用哪个新策略。
假如我们新增一个归并排序算法:
java
class MergeSort implements SortingStrategy {
@Override
public void sort(int[] array) {
// 实现归并排序算法
}
}
在我们的客户端类要想使用归并排序算法的话就需要进行修改了;
java
public class Main {
public static void main(String[] args) {
int[] data = {5, 2, 8, 1, 3};
Sorter sorter = new Sorter();
sorter.setStrategy(new BubbleSort());
sorter.performSort(data);
// 或者切换到另一个策略
sorter.setStrategy(new QuickSort());
sorter.performSort(data);
// 切换到归并排序
sorter.setStrategy(new MergeSort());
sorter.performSort(data);
}
}
4.1、反射+配置文件优化策略模式
创建一个配置文件,用于存储所支持的不同排序策略的类名。这个配置文件可以是 XML、JSON 或者简单的文本文件,取决于你的喜好和项目的需要。
yml
bubbleSort=your.package.BubbleSort
quickSort=your.package.QuickSort
mergeSort=your.package.MergeSort
修改上下文类:
java
import java.io.IOException;
import java.io.InputStream;
import java.util.Properties;
class Sorter {
private SortingStrategy strategy;
public Sorter() {
loadConfiguration();
}
public void performSort(int[] array) {
strategy.sort(array);
}
private void loadConfiguration() {
Properties properties = new Properties();
try (InputStream inputStream = getClass().getResourceAsStream("strategies.properties")) {
properties.load(inputStream);
String strategyClassName = properties.getProperty("selectedStrategy");
strategy = createStrategyInstance(strategyClassName);
} catch (IOException | ClassNotFoundException | IllegalAccessException | InstantiationException e) {
e.printStackTrace();
// 处理异常,设置默认策略
}
}
private SortingStrategy createStrategyInstance(String className)
throws ClassNotFoundException, IllegalAccessException, InstantiationException {
Class<?> strategyClass = Class.forName(className);
return (SortingStrategy) strategyClass.newInstance();
}
}
通过使用反射和配置文件,你可以实现一种更加灵活的策略模式,避免了新增策略时需要修改客户端代码的问题。至于它要选择哪种策略,我们可以设置成一个变量,通过前端进行传入,让用户自己选择想要的策略,这样如果新增一个策略算法的话,只需要新增一个策略子类实现策略接口重写算法,然后在配置文件中新增一个对应关系即可;
三、总结
策略模式是一种强大的工具,可以帮助我们在代码中处理不同算法的选择问题。通过将算法封装成独立的策略类,我们可以轻松地在运行时切换和扩展这些算法,从而实现更加灵活和可维护的代码。无论是在排序算法还是其他需要动态选择不同实现的情景中,策略模式都是一个值得考虑的设计方案。