C++实现设计模式---策略模式 (Strategy)

策略模式 (Strategy)

策略模式 是一种行为型设计模式,它定义了一系列算法,并将每种算法封装到独立的类中,使得它们可以相互替换。策略模式让算法的变化不会影响使用算法的客户端。


意图

  • 将算法的定义与使用分离。
  • 通过封装和组合的方式,使得算法可以灵活替换。

使用场景

  1. 系统需要动态选择算法

    • 需要在运行时根据条件选择不同的算法实现。
  2. 避免使用大量条件语句

    • 如果系统中有大量的 if-elseswitch 语句,可以使用策略模式将这些条件逻辑封装为独立的策略类。
  3. 算法需要灵活扩展

    • 新增算法时无需修改客户端代码,只需实现新的策略类即可。

参与者角色

  1. 上下文类 (Context)

    • 持有对策略对象的引用,并通过策略接口调用具体策略的方法。
  2. 策略接口 (Strategy)

    • 定义了所有具体策略的公共接口。
  3. 具体策略类 (ConcreteStrategy)

    • 实现策略接口,封装具体的算法逻辑。

示例代码

以下代码展示了策略模式的实现,用于计算不同折扣策略下的商品价格。

cpp 复制代码
#include <iostream>
#include <memory>

// 策略接口:折扣策略
class DiscountStrategy {
public:
    virtual ~DiscountStrategy() = default;
    virtual double calculatePrice(double originalPrice) const = 0; // 计算折后价格
};

// 具体策略类:无折扣
class NoDiscount : public DiscountStrategy {
public:
    double calculatePrice(double originalPrice) const override {
        return originalPrice; // 无折扣,返回原价
    }
};

// 具体策略类:百分比折扣
class PercentageDiscount : public DiscountStrategy {
private:
    double discountRate; // 折扣率

public:
    PercentageDiscount(double rate) : discountRate(rate) {}

    double calculatePrice(double originalPrice) const override {
        return originalPrice * (1 - discountRate); // 按折扣率计算
    }
};

// 具体策略类:固定金额折扣
class FixedAmountDiscount : public DiscountStrategy {
private:
    double discountAmount; // 折扣金额

public:
    FixedAmountDiscount(double amount) : discountAmount(amount) {}

    double calculatePrice(double originalPrice) const override {
        return (originalPrice > discountAmount) ? (originalPrice - discountAmount) : 0; // 不低于0元
    }
};

// 上下文类:价格计算器
class PriceCalculator {
private:
    std::unique_ptr<DiscountStrategy> strategy; // 策略对象

public:
    void setStrategy(std::unique_ptr<DiscountStrategy> newStrategy) {
        strategy = std::move(newStrategy); // 动态设置策略
    }

    double calculate(double originalPrice) const {
        if (strategy) {
            return strategy->calculatePrice(originalPrice); // 调用策略计算价格
        } else {
            throw std::runtime_error("No strategy set!");
        }
    }
};

// 客户端代码
int main() {
    PriceCalculator calculator;

    // 设置无折扣策略
    calculator.setStrategy(std::make_unique<NoDiscount>());
    std::cout << "Original Price: $100, Final Price: $" << calculator.calculate(100) << std::endl;

    // 设置百分比折扣策略
    calculator.setStrategy(std::make_unique<PercentageDiscount>(0.2)); // 20% 折扣
    std::cout << "Original Price: $100, Final Price: $" << calculator.calculate(100) << std::endl;

    // 设置固定金额折扣策略
    calculator.setStrategy(std::make_unique<FixedAmountDiscount>(30)); // 减30元
    std::cout << "Original Price: $100, Final Price: $" << calculator.calculate(100) << std::endl;

    return 0;
}

代码解析

1. 策略接口 (DiscountStrategy)
  • 定义了计算折扣价格的接口:
cpp 复制代码
class DiscountStrategy {
public:
    virtual ~DiscountStrategy() = default;
    virtual double calculatePrice(double originalPrice) const = 0;
};
2. 具体策略类
  • 每个具体策略类实现了 DiscountStrategy 接口,封装了具体的算法逻辑:
cpp 复制代码
class PercentageDiscount : public DiscountStrategy {
private:
    double discountRate;

public:
    PercentageDiscount(double rate) : discountRate(rate) {}

    double calculatePrice(double originalPrice) const override {
        return originalPrice * (1 - discountRate);
    }
};
3. 上下文类 (PriceCalculator)
  • PriceCalculator 类持有对策略对象的引用,负责调用策略的 calculatePrice 方法:
cpp 复制代码
class PriceCalculator {
private:
    std::unique_ptr<DiscountStrategy> strategy;

public:
    void setStrategy(std::unique_ptr<DiscountStrategy> newStrategy) {
        strategy = std::move(newStrategy);
    }

    double calculate(double originalPrice) const {
        if (strategy) {
            return strategy->calculatePrice(originalPrice);
        } else {
            throw std::runtime_error("No strategy set!");
        }
    }
};
4. 客户端
  • 客户端通过上下文类设置不同的策略对象,实现动态切换算法:
cpp 复制代码
calculator.setStrategy(std::make_unique<NoDiscount>());
std::cout << "Final Price: $" << calculator.calculate(100) << std::endl;

calculator.setStrategy(std::make_unique<PercentageDiscount>(0.2));
std::cout << "Final Price: $" << calculator.calculate(100) << std::endl;

优缺点

优点
  1. 算法独立
    • 每种算法封装在独立的类中,易于扩展和维护。
  2. 动态切换
    • 可以在运行时灵活替换算法,而无需修改客户端代码。
  3. 消除条件语句
    • 避免了大量的 if-elseswitch 语句。
缺点
  1. 增加系统复杂性
    • 每种策略需要定义一个类,可能增加系统的类数量。
  2. 客户端必须了解策略
    • 客户端需要知道有哪些策略可用,并显式设置策略。

适用场景

  1. 系统中有多种算法可以选择

    • 如排序算法、折扣计算、加密算法等。
  2. 需要动态切换算法

    • 在运行时根据条件选择最优的算法。
  3. 消除条件判断

    • 当系统中有大量的条件分支时,可以使用策略模式将分支逻辑替换为独立的策略类。

总结

策略模式通过将算法封装为独立的类,使得算法可以灵活切换并独立扩展。它是一种非常灵活的设计模式,特别适用于需要动态选择算法的场景。

相关推荐
Say-hai1 小时前
QT中的字符串类型
网络·c++·qt
難釋懷2 小时前
解释器模式
设计模式·解释器模式
不如学也2 小时前
c++ 17 constexpr
开发语言·c++
baiyu332 小时前
C++ Primer Notes(4): 变量初始化和作用域
c++
IOT-Power3 小时前
<C++学习> C++ Boost 字符串操作教程
c++
1e-123 小时前
【数据结构高阶】B-树
数据结构·c++·b树
誓约酱3 小时前
Linux下文件操作相关接口
linux·运维·服务器·c语言·c++·后端
赵宁灬学长4 小时前
23种设计模式
设计模式
计算机小混子4 小时前
C++实现设计模式---代理模式 (Proxy)
c++·设计模式·代理模式