设计模式-策略模式

文章目录

一、前言

在软件设计中,我们经常会面临需要根据不同情况选择不同算法或方法的问题。这些情况可能是基于不同的输入、不同的需求或不同的环境。策略模式(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();
    }
}

通过使用反射和配置文件,你可以实现一种更加灵活的策略模式,避免了新增策略时需要修改客户端代码的问题。至于它要选择哪种策略,我们可以设置成一个变量,通过前端进行传入,让用户自己选择想要的策略,这样如果新增一个策略算法的话,只需要新增一个策略子类实现策略接口重写算法,然后在配置文件中新增一个对应关系即可;

三、总结

策略模式是一种强大的工具,可以帮助我们在代码中处理不同算法的选择问题。通过将算法封装成独立的策略类,我们可以轻松地在运行时切换和扩展这些算法,从而实现更加灵活和可维护的代码。无论是在排序算法还是其他需要动态选择不同实现的情景中,策略模式都是一个值得考虑的设计方案。

相关推荐
丶白泽3 小时前
重修设计模式-结构型-组合模式
设计模式·组合模式
yunhuibin4 小时前
ffmpeg面向对象——参数配置秘密探索及其设计模式
学习·设计模式·ffmpeg
_祝你今天愉快5 小时前
技术成神之路:设计模式(十四)享元模式
java·设计模式
蔚一6 小时前
Java设计模式—面向对象设计原则(三) -----> 依赖倒转原则DIP(完整详解,附有代码+案例)
java·开发语言·设计模式·intellij-idea·依赖倒置原则
丶白泽7 小时前
重修设计模式-概览
java·设计模式
java_heartLake10 小时前
设计模式之建造者模式
java·设计模式·建造者模式
G皮T10 小时前
【设计模式】创建型模式(四):建造者模式
java·设计模式·编程·建造者模式·builder·建造者
战神刘玉栋11 小时前
《程序猿之设计模式实战 · 观察者模式》
python·观察者模式·设计模式
nakyoooooo12 小时前
【设计模式】工厂模式、单例模式、观察者模式、发布订阅模式
观察者模式·单例模式·设计模式
严文文-Chris13 小时前
【设计模式-享元】
android·java·设计模式