• 14 C++设计模式之策略(Strategy)模式


    策略(Strategy)模式定义

    策略模式(Startegy):它定义了算法家族,分别封装起来,让他们之间可以互相替换,此模式让算法的变化,不会影响到使用算法的客户。策略模式是一种定义一系列算法的方法,从概念上来看,所有这些算法完成的都是相同的工作,只是实现不同,它可以以相同的方式调用所有的算法,减少了各种算法类与使用算法类之间的耦合。

    策略(Strategy)模式优缺点

    优点
    • 可以在运行时切换对象内的算法。
    • 可以将算法的实现和使用算法的代码隔离开来。
    • 可以使用组合来代替继承。
    • 开闭原则。你无需对上下文进行修改就能够引入新的策略。
    缺点
    • 如果你的算法极少发生改变,那么没有任何理由引入新的类和接口。使用该模式只会让程序过于复杂。
    • 客户端必须知晓策略间的不同——它需要选择合适的策略。
    • 许多现代编程语言支持函数类型功能,允许你在一组匿名函数中实现不同版本的算法。这样,你使用这些函数的方式就和使用策略对象时完全相同,无需借助额外的类和接口来保持代码简洁

    策略(Strategy)模式构成与实现

    构成
    • 上下文(Context)维护指向具体策略的引用,且仅通过策略接口与该对象进行交流。
    • 策略(Strategy)接口是所有具体策略的通用接口,它声明了一个上下文用于执行策略的方法。
    • 具体策略(Concrete Strategies)实现了上下文所用算法的各种不同变体。
    • 当上下文需要运行算法时,它会在其已连接的策略对象上调用执行方法。上下文不清楚其所涉及的策略类型与算法的执行方式。
    • 客户端(Client)会创建一个特定策略对象并将其传递给上下文。上下文则会提供一个设置器以便客户端在运行时替换相关联的策略。
    实例

    Strategy.h:

    #ifndef STRATEGY_H_
    #define STRATEGY_H_
    
    #include 
    
    // 抽象策略类: 排序
    class Sort {
     public:
        virtual void sortVector(std::vector<int> &arr) = 0;
    };
    
    #endif  // STRATEGY_H_
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    ConcreteStrategy.h:

    #ifndef CONCRETE_STRATEGY_H_
    #define CONCRETE_STRATEGY_H_
    
    #include 
    #include 
    #include 
    #include 
    #include "Strategy.h"
    
    // 打印vector内容
    void printVector(const std::string prefix, const std::vector<int> &vi) {
        std::cout << prefix;
        for (auto i : vi) {
            std::cout << " " << i;
        }
        std::cout << std::endl;
    }
    
    // 具体策略类: 冒泡排序
    class BubbleSort : public Sort {
     public:
        void sortVector(std::vector<int> &vi) override {
            printVector("冒泡排序前:", vi);
            int len = vi.size();
            // 轮次: 从1到n-1轮
            for (int i = 0; i < len - 1; ++i) {
                // 优化: 判断本轮是否有交换元素, 如果没交换则可直接退出
                bool is_exchange = false;
    
                for (int j = 0; j < len - i - 1; ++j) {
                    if (vi[j] > vi[j+1]) {
                        std::swap(vi[j], vi[j+1]);
                        is_exchange = true;
                    }
                }
    
                // 如果本轮无交换, 则可以直接退出
                if (!is_exchange) {
                    printVector("冒泡排序后:", vi);
                    return;
                }
            }
            printVector("冒泡排序后:", vi);
        }
    };
    
    // 具体策略类: 选择排序
    class SelectionSort : public Sort {
     public:
        void sortVector(std::vector<int> &vi) override {
            printVector("选择排序前:", vi);
            // 需要进行 n-1 轮
            for (int i = 0; i < vi.size() - 1; ++i) {
                // 找到此轮的最小值下标
                int min_index = i;
                for (int j = i + 1; j < vi.size(); ++j) {
                    if (vi[j] < vi[min_index]) {
                        min_index = j;
                    }
                }
    
                std::swap(vi[i], vi[min_index]);
            }
            printVector("选择排序后:", vi);
        }
    };
    
    // 具体策略类: 插入排序
    class InsertionSort : public Sort {
     public:
        void sortVector(std::vector<int> &vi) override {
            printVector("插入排序前:", vi);
            // 第一轮不需要操作, 第二轮比较一次, 第n轮比较 n-1 次
            for (int i = 1; i < vi.size(); ++i) {
                // 存储待插入的值和下标
                int insert_value = vi[i];
                int j = i - 1;
    
                while (j >= 0 && vi[j] > insert_value) {
                    vi[j + 1] = vi[j];  // 如果左侧的已排序元素比目标值大, 那么右移
                    j--;
                }
    
                // 注意这里insert_index 需要+1
                vi[j + 1] = insert_value;
            }
            printVector("插入排序后:", vi);
        }
    };
    
    #endif  // CONCRETE_STRATEGY_H_
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91

    Context.h

    #ifndef CONTEXT_H_
    #define CONTEXT_H_
    
    #include 
    #include "Strategy.h"
    
    class ArrayHandler {
     public:
        void sortVector(std::vector<int> &arr) {
            return sort_->sortVector(arr);
        }
        void setSortStrategy(Sort* sort) {
            sort_ = sort;
        }
    
     private:
        Sort *sort_;
    };
    
    #endif  // CONTEXT_H_
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20

    main.cpp

    #include 
    #include 
    #include 
    #include 
    #include "ConcreteStrategy.h"
    #include "Context.h"
    
    std::vector<int> test_array = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25};
    
    int main() {
    
        system("chcp 65001");
        ArrayHandler array_handler;
    
        {
            // 冒泡排序
            BubbleSort* bubble_sort = new BubbleSort();
            auto rng = std::default_random_engine {};
            std::shuffle(std::begin(test_array), std::end(test_array), rng);
            array_handler.setSortStrategy(bubble_sort);
            array_handler.sortVector(test_array);
            delete bubble_sort;
        }
    
        {
            // 选择排序
            SelectionSort* select_sort = new SelectionSort();
            auto rng = std::default_random_engine {};
            std::shuffle(std::begin(test_array), std::end(test_array), rng);
            array_handler.setSortStrategy(select_sort);
            array_handler.sortVector(test_array);
            delete select_sort;
        }
    
        {
            // 插入排序
            InsertionSort* insert_sort = new InsertionSort();
            auto rng = std::default_random_engine {};
            std::shuffle(std::begin(test_array), std::end(test_array), rng);
            array_handler.setSortStrategy(insert_sort);
            array_handler.sortVector(test_array);
            delete insert_sort;
        }
    
        system("pause");
        return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
  • 相关阅读:
    [附源码]java毕业设计基于Java的护肤品网站
    南大通用数据库-Gbase-8a-学习-25-常用系统表查询语句
    深度学习(七)——神经网络的卷积操作
    Kendo UI Grid 批量编辑使用总结
    【EMQX】2.1.6.1 安装环境与官方文档
    Lua数据文件
    新零售数智化转型,需要怎样的数据底座?
    gson如何序列化子类
    大数据之力:从数据湖到数据智能的升级之路
    SpringMVC实现文件上传和下载功能
  • 原文地址:https://blog.csdn.net/qq_45531502/article/details/126419075