设计模式——策略模式

定义与概念

策略模式(Strategy Pattern)是一种行为设计模式。它定义了一系列算法,将每个算法都封装起来,并且使它们可以相互替换。此模式让算法的变化独立于使用算法的客户。

简单来说,就好比在一个角色扮演游戏中,角色的攻击行为可以有多种策略,如近战攻击、远程攻击、魔法攻击等。这些不同的攻击策略可以被封装成不同的类,并且可以在游戏运行过程中根据实际情况(如角色装备的武器、技能等)进行切换。

结构组成

  • 策略(Strategy)接口:
    这是所有具体策略类的共同接口,它定义了策略方法的签名。例如,在一个路径规划系统中,策略接口可能定义了一个findPath()方法,用于寻找从一个点到另一个点的路径。
  • 具体策略(Concrete Strategy)类:
    实现了策略接口,提供了具体的算法实现。在路径规划系统中,可能有 "最短路径策略" 类,它的findPath()方法会使用迪杰斯特拉算法来寻找最短路径;还有 "随机路径策略" 类,它的findPath()方法会随机生成一条可行路径。
  • 上下文(Context)类:
    它持有一个策略接口的引用,用于调用具体的策略方法。上下文类的主要职责是维护策略对象,并在需要时调用策略对象的方法。在游戏角色攻击的例子中,游戏角色类就是上下文类,它维护一个攻击策略对象的引用,当需要进行攻击时,就调用这个攻击策略对象的attack()方法。

工作原理

客户端(使用策略的代码)创建一个具体策略对象,并将其传递给上下文类。上下文类在执行相关操作时,通过其持有的策略接口引用调用具体策略对象的方法。

例如,在一个文本格式化系统中,有 "加粗格式策略" 和 "斜体格式策略" 等具体策略类。上下文类(文本格式化器)可以接收用户选择的具体格式策略对象,当用户要求格式化文本时,文本格式化器就调用当前策略对象的format()方法来对文本进行相应的格式化处理。

代码示例

首先是策略接口,以排序策略为例:

cpp 复制代码
class SortStrategy {
public:
    virtual void sort(int arr[], int size) = 0;
};

具体策略类 - 冒泡排序:

cpp 复制代码
class BubbleSortStrategy : public SortStrategy {
public:
    void sort(int arr[], int size) override {
        for (int i = 0; i < size - 1; ++i) {
            for (int j = 0; j < size - i - 1; ++j) {
                if (arr[j] > arr[j + 1]) {
                    int temp = arr[j];
                    arr[j] = arr[j + 1];
                    arr[j + 1] = temp;
                }
            }
        }
    }
};

具体策略类 - 快速排序:

cpp 复制代码
class QuickSortStrategy : public SortStrategy {
public:
    int partition(int arr[], int low, int high) {
        int pivot = arr[high];
        int i = (low - 1);
        for (int j = low; j <= high - 1; ++j) {
            if (arr[j] <= pivot) {
                i++;
                int temp = arr[i];
                arr[i] = arr[j];
                arr[j] = temp;
            }
        }
        int temp = arr[i + 1];
        arr[i + 1] = arr[high];
        arr[high] = temp;
        return (i + 1);
    }
    void sort(int arr[], int size) override {
        std::stack<int> stack;
        stack.push(0);
        stack.push(size - 1);
        while (!stack.empty()) {
            int high = stack.top();
            stack.pop();
            int low = stack.top();
            stack.pop();
            int p = partition(arr, low, high);
            if (p - 1 > low) {
                stack.push(low);
                stack.push(p - 1);
            }
            if (p + 1 < high) {
                stack.push(p + 1);
                stack.push(high);
            }
        }
    }
};

上下文类:

cpp 复制代码
class Sorter {
private:
    SortStrategy* strategy;
public:
    Sorter(SortStrategy* s) : strategy(s) {}
    void setStrategy(SortStrategy* s) {
        strategy = s;
    }
    void sort(int arr[], int size) {
        strategy->sort(arr, size);
    }
};

使用示例:

cpp 复制代码
int main() {
    int arr[] = {5, 4, 3, 2, 1};
    int size = sizeof(arr) / sizeof(arr[0]);
    BubbleSortStrategy bubbleSort;
    Sorter sorter(&bubbleSort);
    sorter.sort(arr, size);
    for (int i = 0; i < size; ++i) {
        std::cout << arr[i] << " ";
    }
    std::cout << std::endl;
    QuickSortStrategy quickSort;
    sorter.setStrategy(&quickSort);
    sorter.sort(arr, size);
    for (int i = 0; i < size; ++i) {
        std::cout << arr[i] << " ";
    }
    return 0;
}

优点

  • 可替换性:
    可以方便地替换算法(策略)。在上述排序的例子中,如果发现一种新的更高效的排序算法,只需要创建一个新的具体策略类实现排序策略接口,然后在上下文中替换原来的策略即可,不需要修改上下文类的其他部分。
  • 可维护性和可扩展性:
    将不同的算法封装在各自的类中,使得代码结构清晰,易于维护和扩展。如果要修改某个排序算法的实现,只需要在对应的具体策略类中进行修改,不会影响到其他策略和上下文类的大部分代码。
  • 符合开闭原则:
    对扩展开放,对修改关闭。当需要添加新的策略时,只需要实现策略接口,创建新的具体策略类,而不需要修改已有的代码。

缺点

  • 增加类的数量:
    每一个策略都需要一个具体策略类来实现,当策略较多时,会导致类的数量增加,使得代码的复杂性提高。例如,在一个复杂的金融交易系统中,如果有大量的交易策略,会产生很多策略类文件。
  • 客户端需要了解策略:
    客户端需要知道有哪些策略可供选择,并且需要知道如何创建和使用这些策略。在一些复杂的系统中,这可能会增加客户端代码的复杂性,尤其是当策略的选择和使用条件比较复杂时。
相关推荐
forestsea15 分钟前
【Java 解释器模式】实现高扩展性的医学专家诊断规则引擎
java·人工智能·设计模式·解释器模式
小白不太白9503 小时前
设计模式之 命令模式
设计模式·命令模式
吃汉堡吃到饱3 小时前
【创建型设计模式】单例模式
单例模式·设计模式
小白不太白9503 小时前
设计模式之 备忘录模式
服务器·设计模式·备忘录模式
入门到跑路3 小时前
【君正T31开发记录】8.了解rtsp协议及设计模式
网络协议·设计模式
小白不太白9503 小时前
设计模式之 解释器模式
java·设计模式·解释器模式
小白不太白9504 小时前
设计模式之 代理模式
设计模式·代理模式
吃汉堡吃到饱4 小时前
【创建型设计模式】工厂模式
设计模式
程序员与背包客_CoderZ4 小时前
C++设计模式——Singleton单例模式
c语言·开发语言·c++·单例模式·设计模式