行为型模式:⑨策略模式(Strategy Pattern)

行为型模式:⑨策略模式(Strategy Pattern)

核心思想

定义一系列可互换的算法(策略),将每个算法封装为独立的类/结构体,使算法的选择、切换与使用算法的客户端(上下文)分离。核心价值是:

  • 消除大量if-else/switch条件判断,用“组合+多态”替代硬编码的条件分支;
  • 算法可动态切换,客户端可根据需求在运行时选择不同策略;
  • 新增/修改算法时无需修改客户端和其他策略,仅需新增/调整策略类,符合“开闭原则”;
  • 算法复用性强,同一策略可被多个客户端共享。

核心本质

算法封装+动态委派,将“做什么”(客户端需求)与“怎么做”(具体算法)解耦,让算法成为可灵活替换的“组件”。

典型场景

  • 支付方式选择(支付宝、微信、银行卡支付,不同支付算法可切换);
  • 排序算法切换(冒泡排序、快速排序、归并排序,根据数据量动态选择);
  • 折扣计算(会员折扣、节日折扣、满减折扣,不同场景自动切换);
  • 数据校验规则(手机号校验、邮箱校验、身份证校验,按需选择校验策略)。

C语言实现(结构体+函数指针+组合)

C语言无类和继承,通过“结构体模拟策略接口”“函数指针定义算法行为”“上下文持有策略指针”,实现算法的封装与动态切换。核心是:上下文通过策略指针调用具体算法,切换策略只需修改指针指向。

场景示例

订单支付系统:

  • 抽象策略(PaymentStrategy):用函数指针定义统一支付接口(pay);
  • 具体策略:支付宝支付(AlipayStrategy)、微信支付(WechatPayStrategy)、银行卡支付(BankCardStrategy),实现各自的支付逻辑;
  • 上下文(Order):持有当前支付策略指针,提供切换策略、执行支付的接口,维护订单金额等上下文数据。

实现代码

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

// 最大支付备注长度
#define MAX_REMARK_LEN 64

// -------------------------- 1. 抽象策略(PaymentStrategy):统一算法接口 --------------------------
// 策略结构体:包含支付函数指针(核心接口)和策略名称
typedef struct PaymentStrategy {
    const char* name; // 策略名称(用于日志)
    // 支付算法:接收订单金额、备注,返回支付结果(0=成功,-1=失败)
    int (*pay)(float amount, const char* remark);
} PaymentStrategy;

// -------------------------- 2. 具体策略实现(不同支付方式) --------------------------
// 具体策略1:支付宝支付
int alipay_pay(float amount, const char* remark) {
    printf("\n=== 【%s】 ===\n", "支付宝支付");
    printf("支付金额:%.2f 元\n", amount);
    printf("备注:%s\n", remark);
    printf("执行支付宝支付逻辑(调用支付宝SDK、验证签名...)\n");
    printf("支付宝支付成功!\n");
    return 0;
}

// 支付宝策略实例(全局静态变量,无需动态分配)
PaymentStrategy AlipayStrategy = {
    .name = "支付宝支付",
    .pay = alipay_pay
};

// 具体策略2:微信支付
int wechat_pay(float amount, const char* remark) {
    printf("\n=== 【%s】 ===\n", "微信支付");
    printf("支付金额:%.2f 元\n", amount);
    printf("备注:%s\n", remark);
    printf("执行微信支付逻辑(调用微信SDK、验证openid...)\n");
    printf("微信支付成功!\n");
    return 0;
}

// 微信策略实例
PaymentStrategy WechatPayStrategy = {
    .name = "微信支付",
    .pay = wechat_pay
};

// 具体策略3:银行卡支付
int bank_card_pay(float amount, const char* remark) {
    printf("\n=== 【%s】 ===\n", "银行卡支付");
    printf("支付金额:%.2f 元\n", amount);
    printf("备注:%s\n", remark);
    printf("执行银行卡支付逻辑(验证卡号、密码、短信验证码...)\n");
    printf("银行卡支付成功!\n");
    return 0;
}

// 银行卡策略实例
PaymentStrategy BankCardStrategy = {
    .name = "银行卡支付",
    .pay = bank_card_pay
};

// -------------------------- 3. 上下文(Order):使用策略的客户端 --------------------------
typedef struct Order {
    float amount;                  // 订单金额(上下文数据)
    PaymentStrategy* current_strategy; // 持有当前策略指针(核心)
    // 上下文操作接口
    void (*set_strategy)(struct Order* self, PaymentStrategy* strategy); // 切换策略
    int (*pay_order)(struct Order* self, const char* remark);            // 执行支付(委派给策略)
    void (*destroy)(struct Order* self);
} Order;

// 上下文:切换策略
void order_set_strategy(Order* self, PaymentStrategy* strategy) {
    if (strategy == NULL) {
        printf("错误:支付策略不能为空!\n");
        return;
    }
    self->current_strategy = strategy;
    printf("已切换支付方式为:%s\n", strategy->name);
}

// 上下文:执行支付(委托当前策略处理)
int order_pay_order(Order* self, const char* remark) {
    if (self->current_strategy == NULL) {
        printf("错误:未选择支付方式!\n");
        return -1;
    }
    printf("订单开始支付,金额:%.2f 元\n", self->amount);
    // 委派给当前策略的pay方法(核心:算法调用解耦)
    return self->current_strategy->pay(self->amount, remark);
}

// 上下文:销毁
void order_destroy(Order* self) {
    free(self);
    printf("\n订单对象已销毁\n");
}

// 创建订单(上下文)
Order* create_order(float amount) {
    Order* order = (Order*)malloc(sizeof(Order));
    if (order == NULL) {
        perror("malloc failed");
        exit(EXIT_FAILURE);
    }
    order->amount = amount;
    order->current_strategy = NULL; // 初始未选择策略
    order->set_strategy = order_set_strategy;
    order->pay_order = order_pay_order;
    order->destroy = order_destroy;
    printf("创建订单成功,金额:%.2f 元\n", amount);
    return order;
}

// -------------------------- 测试代码(客户端) --------------------------
int main() {
    // 1. 创建订单(上下文)
    Order* order = create_order(299.99f);
    printf("========================================\n");

    // 2. 选择支付宝支付(切换策略1)
    order->set_strategy(order, &AlipayStrategy);
    order->pay_order(order, "购买电子产品");

    // 3. 切换为微信支付(切换策略2)
    printf("\n========================================\n");
    order->set_strategy(order, &WechatPayStrategy);
    order->pay_order(order, "购买电子产品(微信补付)");

    // 4. 切换为银行卡支付(切换策略3)
    printf("\n========================================\n");
    order->set_strategy(order, &BankCardStrategy);
    order->pay_order(order, "购买电子产品(银行卡支付)");

    // 5. 未选择策略时支付(错误场景)
    printf("\n========================================\n");
    Order* empty_order = create_order(199.99f);
    empty_order->pay_order(empty_order, "未选支付方式测试");

    // 6. 销毁资源
    printf("\n========================================\n");
    order->destroy(order);
    empty_order->destroy(empty_order);

    return 0;
}

C语言实现关键要点

  1. 抽象策略接口(函数指针)PaymentStrategy结构体通过pay函数指针定义统一支付接口,所有具体策略都实现该接口,确保上下文可通过统一方式调用不同算法。
  2. 策略实例化(全局静态变量):具体策略(支付宝、微信等)为全局静态结构体实例,无需动态分配内存,切换策略仅修改指针指向,效率高。
  3. 上下文持有策略指针Ordercurrent_strategy指针指向当前策略,上下文不关心策略的具体实现,仅通过接口调用,实现解耦。
  4. 动态切换策略:上下文提供set_strategy接口,客户端可在运行时灵活切换策略(如从支付宝切换到微信),无需修改上下文代码。
  5. 消除条件判断:客户端无需用if-else判断选择哪种支付方式,直接通过切换策略指针实现,代码更简洁、可维护。
  6. 扩展性:新增支付方式(如Apple Pay)时,仅需定义新的PaymentStrategy实例并实现pay函数,客户端直接切换即可,无需修改上下文和其他策略,符合“开闭原则”。
  7. 内存管理:策略为全局静态变量(生命周期贯穿程序),上下文手动malloc/free,避免内存泄漏;策略切换无额外内存开销。

C++实现(类+继承+多态+智能指针)

C++通过“抽象基类+继承”定义策略接口,利用多态实现算法的动态分发,上下文持有抽象策略的智能指针,支持策略的动态切换和自动内存管理,代码更符合面向对象风格。

场景示例

同C语言:订单支付系统,抽象策略基类PaymentStrategy定义支付接口,具体策略子类实现不同支付逻辑,上下文Order通过多态调用策略。

实现代码

#include <iostream>
#include <string>
#include <memory> // 智能指针(自动管理内存)

using namespace std;

// -------------------------- 1. 抽象策略(PaymentStrategy):抽象基类 --------------------------
class PaymentStrategy {
public:
    virtual ~PaymentStrategy() = default; // 虚析构:确保子类析构被调用
    // 纯虚函数:统一支付接口(算法核心)
    virtual bool pay(float amount, const string& remark) const = 0;
    // 获取策略名称(用于日志)
    virtual string getName() const = 0;
};

// -------------------------- 2. 具体策略类(不同支付方式) --------------------------
// 具体策略1:支付宝支付
class AlipayPay : public PaymentStrategy {
public:
    bool pay(float amount, const string& remark) const override {
        cout << "\n=== 【" << getName() << "】 ===" << endl;
        cout << "支付金额:" << fixed << setprecision(2) << amount << " 元" << endl;
        cout << "备注:" << remark << endl;
        cout << "执行支付宝支付逻辑(调用支付宝SDK、验证签名...)" << endl;
        cout << "支付宝支付成功!" << endl;
        return true;
    }

    string getName() const override {
        return "支付宝支付";
    }
};

// 具体策略2:微信支付
class WechatPay : public PaymentStrategy {
public:
    bool pay(float amount, const string& remark) const override {
        cout << "\n=== 【" << getName() << "】 ===" << endl;
        cout << "支付金额:" << fixed << setprecision(2) << amount << " 元" << endl;
        cout << "备注:" << remark << endl;
        cout << "执行微信支付逻辑(调用微信SDK、验证openid...)" << endl;
        cout << "微信支付成功!" << endl;
        return true;
    }

    string getName() const override {
        return "微信支付";
    }
};

// 具体策略3:银行卡支付
class BankCardPay : public PaymentStrategy {
public:
    bool pay(float amount, const string& remark) const override {
        cout << "\n=== 【" << getName() << "】 ===" << endl;
        cout << "支付金额:" << fixed << setprecision(2) << amount << " 元" << endl;
        cout << "备注:" << remark << endl;
        cout << "执行银行卡支付逻辑(验证卡号、密码、短信验证码...)" << endl;
        cout << "银行卡支付成功!" << endl;
        return true;
    }

    string getName() const override {
        return "银行卡支付";
    }
};

// -------------------------- 3. 上下文(Order):使用策略的客户端 --------------------------
class Order {
public:
    // 构造函数:初始化订单金额,默认无策略
    Order(float amount) : amount_(amount), strategy_(nullptr) {
        cout << "创建订单成功,金额:" << fixed << setprecision(2) << amount_ << " 元" << endl;
    }

    // 切换策略(智能指针管理策略对象,自动销毁旧策略)
    void setStrategy(unique_ptr<PaymentStrategy> strategy) {
        if (!strategy) {
            cout << "错误:支付策略不能为空!" << endl;
            return;
        }
        strategy_ = move(strategy); // 转移智能指针所有权
        cout << "已切换支付方式为:" << strategy_->getName() << endl;
    }

    // 执行支付(多态调用策略的pay方法)
    bool payOrder(const string& remark) const {
        if (!strategy_) {
            cout << "错误:未选择支付方式!" << endl;
            return false;
        }
        cout << "订单开始支付,金额:" << fixed << setprecision(2) << amount_ << " 元" << endl;
        return strategy_->pay(amount_, remark); // 多态分发:调用具体策略的支付逻辑
    }

private:
    float amount_; // 订单金额(上下文数据)
    unique_ptr<PaymentStrategy> strategy_; // 持有当前策略(智能指针自动管理内存)
};

// -------------------------- 测试代码(客户端) --------------------------
int main() {
    // 1. 创建订单(上下文)
    Order order(299.99f);
    cout << "========================================\n";

    // 2. 选择支付宝支付(切换策略1)
    order.setStrategy(make_unique<AlipayPay>());
    order.payOrder("购买电子产品");

    // 3. 切换为微信支付(切换策略2)
    cout << "\n========================================\n";
    order.setStrategy(make_unique<WechatPay>());
    order.payOrder("购买电子产品(微信补付)");

    // 4. 切换为银行卡支付(切换策略3)
    cout << "\n========================================\n";
    order.setStrategy(make_unique<BankCardPay>());
    order.payOrder("购买电子产品(银行卡支付)");

    // 5. 未选择策略时支付(错误场景)
    cout << "\n========================================\n";
    Order empty_order(199.99f);
    empty_order.payOrder("未选支付方式测试");

    return 0; // 智能指针自动销毁策略和订单对象,无需手动释放
}

C++实现关键要点

  1. 抽象基类+多态PaymentStrategy定义纯虚函数paygetName,具体策略子类继承并实现,上下文通过基类指针(智能指针)调用,实现多态分发,解耦上下文与具体策略。
  2. 智能指针管理内存:上下文用unique_ptr持有策略对象,自动创建和销毁策略,避免内存泄漏;move语义转移策略所有权,切换策略时自动释放旧策略。
  3. 动态切换策略:上下文提供setStrategy方法,客户端通过make_unique创建具体策略并传递,切换过程简洁高效,无需手动管理策略生命周期。
  4. 封装性强:策略的具体实现(如支付SDK调用、签名验证)隐藏在子类中,上下文仅依赖抽象基类,不关心具体实现,符合“依赖倒置原则”。
  5. 扩展性极佳:新增支付方式(如Apple Pay)时,仅需创建新的子类继承PaymentStrategy并实现纯虚函数,客户端调用setStrategy切换即可,无需修改上下文和其他策略,完全符合“开闭原则”。
  6. 类型安全:C++的编译期类型检查和多态机制,避免C语言中函数指针绑定错误或类型转换风险,代码更可靠;虚析构函数确保子类析构被正确调用。

策略模式核心总结(C vs C++)

对比维度C语言实现C++语言实现
接口定义结构体+函数指针抽象基类+纯虚函数(多态)
内存管理全局静态策略实例+上下文手动malloc/free智能指针(unique_ptr)自动管理,RAII原则
策略切换直接修改上下文的策略指针调用setStrategy方法,转移智能指针所有权
类型安全依赖手动指针操作,风险高编译期类型检查+多态,类型安全
封装性策略实现与接口在同一结构体,封装性一般策略实现隐藏在子类中,私有成员不可访问,封装性强
扩展性新增策略需定义结构体+函数指针,手动绑定新增策略仅需继承抽象基类,实现纯虚函数
代码可读性函数指针和全局实例,可读性一般类继承结构清晰,多态调用直观,可读性强

通用关键要点(跨语言)

设计原则

  • 开闭原则:新增/修改算法仅需调整策略类,无需修改上下文和客户端;
  • 依赖倒置原则:上下文依赖策略抽象,不依赖具体策略实现;
  • 单一职责原则:每个策略类仅负责自身的算法逻辑,上下文仅负责策略管理和调用。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值