当前位置: 首页 > article >正文

C++软件设计模式之策略模式

策略模式的动机、意图和适用场合

1. 动机

在软件开发中,经常会遇到需要在运行时选择不同算法或行为的情况。传统的做法是使用条件语句(如 if-else 或 switch)来选择不同的实现。然而,这种方式有几个缺点:

  • 代码冗长:每个条件分支都需要编写重复的代码。
  • 难以维护:当需要添加新的算法或行为时,需要修改现有的条件语句,容易引入错误。
  • 耦合度高:客户端代码与具体的算法实现紧密耦合,难以扩展和复用。

策略模式通过将算法或行为封装成独立的类(策略类),并通过一个抽象类或接口来定义这些策略类的共同行为,解决了上述问题。

2. 意图

策略模式的意图是定义一系列算法,将它们封装起来,并使它们可以相互替换。策略模式使得算法可以独立于使用它的客户端而变化。

3. 适用场合

策略模式适用于以下几种情况:

  • 多个相关的类仅有行为不同:策略模式可以将这些类的行为提取出来,作为不同的策略类,从而避免类的重复代码。
  • 需要使用一个算法的不同变体:客户端可以在运行时根据需要选择不同的算法实现。
  • 算法需要选择或切换:策略模式允许在运行时动态地选择和切换不同的算法。
  • 避免条件语句:通过策略模式,可以减少或消除复杂的条件语句,使代码更加清晰和易于维护。

为什么策略模式是行为型模式而不是结构型模式

行为型模式的定义

行为型模式关注对象之间的职责分配和交互。它们主要解决对象如何通信和协作的问题,而不是对象的创建或结构。

策略模式的特点
  1. 关注对象的行为:策略模式的核心是算法或行为的封装和替换,而不是对象的创建或结构。
  2. 动态选择和切换:策略模式允许在运行时动态地选择和切换不同的算法,这依赖于对象之间的交互。
  3. 解耦客户端和算法:客户端代码通过接口与策略类交互,而不是直接调用具体的算法实现,这使得客户端代码与具体算法实现解耦。
  4. 增强灵活性和可扩展性:通过将算法封装成独立的类,可以轻松地添加、删除或修改算法,而不会影响客户端代码。
区别于结构型模式
  1. 结构型模式关注对象的组合:结构型模式主要解决如何组合类或对象以形成更大的结构,例如适配器模式、装饰者模式和组合模式等。它们关注的是类或对象的结构和关系。
  2. 行为型模式关注对象的交互:策略模式关注的是对象之间的行为和交互,通过定义不同的策略类,使客户端可以在运行时选择和切换不同的算法。

示例

以下是一个简单的C++示例,展示了如何使用策略模式来封装不同的排序算法。

// 抽象策略类
class SortingStrategy {
public:
    virtual void sort(int* array, int length) = 0;
    virtual ~SortingStrategy() {}
};

// 具体策略类:冒泡排序
class BubbleSort : public SortingStrategy {
public:
    void sort(int* array, int length) override {
        for (int i = 0; i < length - 1; ++i) {
            for (int j = 0; j < length - i - 1; ++j) {
                if (array[j] > array[j + 1]) {
                    std::swap(array[j], array[j + 1]);
                }
            }
        }
    }
};

// 具体策略类:快速排序
class QuickSort : public SortingStrategy {
public:
    void sort(int* array, int length) override {
        quickSort(array, 0, length - 1);
    }

private:
    void quickSort(int* array, int low, int high) {
        if (low < high) {
            int pi = partition(array, low, high);
            quickSort(array, low, pi - 1);
            quickSort(array, pi + 1, high);
        }
    }

    int partition(int* array, int low, int high) {
        int pivot = array[high];
        int i = (low - 1);

        for (int j = low; j < high; j++) {
            if (array[j] <= pivot) {
                i++;
                std::swap(array[i], array[j]);
            }
        }
        std::swap(array[i + 1], array[high]);
        return (i + 1);
    }
};

// 上下文类
class Context {
private:
    SortingStrategy* strategy;

public:
    Context(SortingStrategy* strategy) : strategy(strategy) {}

    void setStrategy(SortingStrategy* strategy) {
        this->strategy = strategy;
    }

    void sortArray(int* array, int length) {
        strategy->sort(array, length);
    }

    ~Context() {
        delete strategy;
    }
};

// 客户端代码
int main() {
    int array[5] = {5, 2, 8, 1, 9};
    Context* context = new Context(new BubbleSort());

    context->sortArray(array, 5);
    for (int i = 0; i < 5; ++i) {
        std::cout << array[i] << " ";
    }
    std::cout << std::endl;

    context->setStrategy(new QuickSort());
    context->sortArray(array, 5);
    for (int i = 0; i < 5; ++i) {
        std::cout << array[i] << " ";
    }
    std::cout << std::endl;

    delete context;
    return 0;
}

总结

策略模式是一种行为型设计模式,它通过将算法或行为封装成独立的类,使客户端可以在运行时动态地选择和切换不同的算法。策略模式关注对象的行为和交互,而不是对象的创建或结构,因此它被归类为行为型模式。通过使用策略模式,可以提高代码的灵活性和可维护性,减少条件语句的使用,使代码更加清晰和易于扩展。

使用策略模式,封装不同的信号滤波处理算法的C++代码完整示例

面是一个使用策略模式封装不同信号滤波处理算法的完整C++示例。这个示例中,我们将实现两种不同的滤波策略:简单的平均滤波和中值滤波。

1. 抽象策略类

首先,定义一个抽象的滤波策略类 FilterStrategy,它包含一个纯虚函数 filter,用于定义滤波算法的共同接口。

#include <iostream>
#include <vector>
#include <algorithm>

// 抽象策略类
class FilterStrategy {
public:
    virtual std::vector<double> filter(const std::vector<double>& signal) const = 0;
    virtual ~FilterStrategy() = default;
};

2. 具体策略类

接下来,实现两个具体的滤波策略类:MeanFilter 和 MedianFilter

2.1 平均滤波策略
class MeanFilter : public FilterStrategy {
public:
    std::vector<double> filter(const std::vector<double>& signal) const override {
        int windowSize = 3; // 滤波窗口大小
        int n = signal.size();
        std::vector<double> filteredSignal(n, 0.0);

        for (int i = 0; i < n; ++i) {
            double sum = 0.0;
            int count = 0;
            for (int j = -windowSize / 2; j <= windowSize / 2; ++j) {
                if (i + j >= 0 && i + j < n) {
                    sum += signal[i + j];
                    count++;
                }
            }
            filteredSignal[i] = sum / count;
        }

        return filteredSignal;
    }
};

2.2 中值滤波策略
class MedianFilter : public FilterStrategy {
public:
    std::vector<double> filter(const std::vector<double>& signal) const override {
        int windowSize = 3; // 滤波窗口大小
        int n = signal.size();
        std::vector<double> filteredSignal(n, 0.0);

        for (int i = 0; i < n; ++i) {
            std::vector<double> window;
            for (int j = -windowSize / 2; j <= windowSize / 2; ++j) {
                if (i + j >= 0 && i + j < n) {
                    window.push_back(signal[i + j]);
                }
            }
            std::sort(window.begin(), window.end());
            filteredSignal[i] = window[window.size() / 2];
        }

        return filteredSignal;
    }
};

3. 上下文类

定义一个上下文类 SignalProcessor,它使用一个 FilterStrategy 对象来处理信号。

class SignalProcessor {
private:
    FilterStrategy* strategy;

public:
    SignalProcessor(FilterStrategy* strategy) : strategy(strategy) {}

    void setStrategy(FilterStrategy* strategy) {
        this->strategy = strategy;
    }

    std::vector<double> process(const std::vector<double>& signal) {
        return strategy->filter(signal);
    }

    ~SignalProcessor() {
        delete strategy;
    }
};

4. 客户端代码

最后,编写客户端代码来演示如何使用不同的滤波策略。

int main() {
    // 创建一个信号
    std::vector<double> signal = {1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0};

    // 创建滤波策略对象
    FilterStrategy* meanFilter = new MeanFilter();
    FilterStrategy* medianFilter = new MedianFilter();

    // 创建信号处理器对象,并设置初始滤波策略
    SignalProcessor processor(meanFilter);

    // 使用平均滤波处理信号
    std::vector<double> filteredSignal = processor.process(signal);
    std::cout << "Mean Filter: ";
    for (double value : filteredSignal) {
        std::cout << value << " ";
    }
    std::cout << std::endl;

    // 切换到中值滤波策略
    processor.setStrategy(medianFilter);

    // 使用中值滤波处理信号
    filteredSignal = processor.process(signal);
    std::cout << "Median Filter: ";
    for (double value : filteredSignal) {
        std::cout << value << " ";
    }
    std::cout << std::endl;

    // 释放资源
    delete meanFilter;
    delete medianFilter;

    return 0;
}

总结

在这个示例中,我们使用策略模式封装了两种不同的信号滤波算法:平均滤波和中值滤波。通过定义抽象的 FilterStrategy 类和具体的 MeanFilter 及 MedianFilter 类,我们实现了算法的封装和替换。SignalProcessor 类作为上下文类,使用策略对象来处理信号,并可以在运行时动态地切换不同的滤波策略。这种方式提高了代码的灵活性和可维护性。


http://www.kler.cn/a/457908.html

相关文章:

  • 【蓝桥杯选拔赛真题87】python输出字符串 第十五届青少年组蓝桥杯python选拔赛真题 算法思维真题解析
  • 从0实现llama3
  • 1、ELK的架构和安装
  • MIT Cheetah 四足机器人的动力学及算法 (I) —— 简化动力学模型
  • 【AndroidAPP】权限被拒绝:[android.permission.READ_EXTERNAL_STORAGE],USB设备访问权限系统报错
  • InstructGPT:基于人类反馈训练语言模型遵从指令的能力
  • 目标检测文献阅读-YOLO:统一的实时目标检测(12.23-12.29)
  • Go的对象在内存中分配原理
  • 使用 Webpack 优雅的构建微前端应用❕
  • C++ 设计模式:工厂方法(Factory Method)
  • QT 学习第十四天
  • 8-Gin 中间件 --[Gin 框架入门精讲与实战案例] 【文末有测试代码】
  • 《XML Schema 字符串数据类型》
  • 【学生管理系统】环境搭建
  • 实测数据处理(CS算法处理:可斜视)——SAR成像算法系列(十一)
  • MVCC实现原理以及解决脏读、不可重复读、幻读问题
  • Docker添加镜像加速器
  • 短视频矩阵账号管理技术源码搭建详解,支持OEM
  • 生成对抗网络,边缘计算,知识图谱,解释性AI
  • 0基础学前端-----CSS DAY11
  • RK3566和Robo_C的EMC防护设计细节
  • MySQL 服务器简介
  • QWT 之 QwtPlotDirectPainter直接绘制
  • LeetCode430周赛T3
  • BAPI_BATCH_CHANGE在更新后不自动更新批次特征
  • 区块链安全常见的攻击——ERC777 重入漏洞 (ERC777 Reentrancy Vulnerability)【5】