
1. 策略模式在C中的核心价值策略模式是我在大型C项目中最常用的设计模式之一。它本质上是一种行为设计模式允许在运行时选择算法或行为。想象一下你正在开发一个支付系统需要支持信用卡、支付宝、微信支付等多种支付方式。如果把这些支付逻辑都硬编码在同一个类里代码会变得臃肿且难以维护。这就是策略模式大显身手的地方。在实际项目中策略模式特别适合以下场景一个系统需要在多种算法中选择一种需要避免暴露复杂的算法实现细节算法可能在未来需要扩展或修改类中包含大量条件语句来选择不同的行为重要提示策略模式不是简单的if-else替换而是通过对象组合来实现行为的动态切换这符合组合优于继承的设计原则。2. 策略模式的经典实现结构让我们通过一个电商折扣系统的例子来拆解策略模式的典型实现。这个系统需要支持会员折扣、节日折扣和满减折扣三种策略。2.1 基础接口定义首先定义策略接口这是所有具体策略的契约class DiscountStrategy { public: virtual ~DiscountStrategy() default; virtual double applyDiscount(double originalPrice) 0; };2.2 具体策略实现然后实现三种具体的折扣策略// 会员折扣策略 class MemberDiscount : public DiscountStrategy { public: double applyDiscount(double originalPrice) override { return originalPrice * 0.9; // 打9折 } }; // 节日折扣策略 class FestivalDiscount : public DiscountStrategy { public: double applyDiscount(double originalPrice) override { return originalPrice * 0.8; // 打8折 } }; // 满减折扣策略 class FullReductionDiscount : public DiscountStrategy { public: double applyDiscount(double originalPrice) override { if(originalPrice 200) { return originalPrice - 50; // 满200减50 } return originalPrice; } };2.3 上下文环境类上下文类持有策略对象的引用并将折扣计算委托给当前策略class ShoppingCart { private: std::unique_ptrDiscountStrategy strategy_; public: explicit ShoppingCart(std::unique_ptrDiscountStrategy strategy nullptr) : strategy_(std::move(strategy)) {} void setStrategy(std::unique_ptrDiscountStrategy strategy) { strategy_ std::move(strategy); } double checkout(double originalPrice) { if(strategy_) { return strategy_-applyDiscount(originalPrice); } return originalPrice; } };3. 策略模式的高级应用技巧3.1 策略对象的生命周期管理在实际项目中策略对象的管理需要特别注意// 使用工厂方法创建策略 std::unique_ptrDiscountStrategy createStrategy(DiscountType type) { switch(type) { case DiscountType::MEMBER: return std::make_uniqueMemberDiscount(); case DiscountType::FESTIVAL: return std::make_uniqueFestivalDiscount(); case DiscountType::FULL_REDUCTION: return std::make_uniqueFullReductionDiscount(); default: return nullptr; } } // 使用示例 ShoppingCart cart; cart.setStrategy(createStrategy(DiscountType::FESTIVAL)); double finalPrice cart.checkout(300);3.2 策略模式与模板的结合C的模板特性可以让策略模式更灵活templatetypename Strategy class GenericShoppingCart { private: Strategy strategy_; public: double checkout(double originalPrice) { return strategy_.applyDiscount(originalPrice); } }; // 使用示例 GenericShoppingCartMemberDiscount cart; double finalPrice cart.checkout(300);3.3 策略模式的性能优化对于性能敏感的场景可以考虑以下优化策略对象复用对于无状态的策略可以共享单例实例策略缓存将常用策略缓存起来避免重复创建内联优化对简单策略使用模板实现让编译器做内联优化4. 实战中的常见问题与解决方案4.1 策略选择逻辑的处理常见误区是将策略选择逻辑分散在各处。推荐的做法// 不好的做法 - 策略选择分散 if(user.isMember()) { cart.setStrategy(std::make_uniqueMemberDiscount()); } else if(isFestival()) { cart.setStrategy(std::make_uniqueFestivalDiscount()); } // 好的做法 - 集中策略选择逻辑 class DiscountStrategyFactory { public: static std::unique_ptrDiscountStrategy create(User user, Date date) { if(user.isMember()) return std::make_uniqueMemberDiscount(); if(isFestival(date)) return std::make_uniqueFestivalDiscount(); return nullptr; } };4.2 策略模式的测试策略策略模式的一个优势是便于单元测试// 测试具体策略 TEST(MemberDiscountTest, ShouldApply10PercentDiscount) { MemberDiscount strategy; ASSERT_EQ(90, strategy.applyDiscount(100)); } // 测试上下文类 TEST(ShoppingCartTest, ShouldUseCurrentStrategy) { ShoppingCart cart(std::make_uniqueTestDiscountStrategy()); ASSERT_EQ(50, cart.checkout(100)); }4.3 策略模式与其他模式的结合在实际项目中策略模式常与其他模式配合使用工厂模式用于创建策略对象组合模式构建复合策略装饰器模式动态添加策略功能5. 性能对比与适用场景分析5.1 策略模式 vs 简单条件语句对比维度策略模式条件语句可维护性高符合开闭原则低修改需要改动现有代码可扩展性高新增策略不影响现有代码低需要修改条件逻辑运行时灵活性高可动态切换低编译时确定性能略低虚函数调用开销高直接跳转代码清晰度高逻辑分离低逻辑混杂5.2 何时使用策略模式建议在以下情况使用策略模式系统需要多种算法变体算法可能在未来发生变化需要避免暴露复杂的数据结构类中包含大量条件语句不建议在以下情况使用算法很少变化性能极度敏感的场合只有一两种简单算法变体6. 现代C中的策略模式演进C11/14/17的新特性让策略模式实现更优雅6.1 使用std::function作为策略class FunctionShoppingCart { private: std::functiondouble(double) strategy_; public: void setStrategy(std::functiondouble(double) strategy) { strategy_ strategy; } double checkout(double price) { return strategy_ ? strategy_(price) : price; } }; // 使用示例 FunctionShoppingCart cart; cart.setStrategy([](double price) { return price * 0.9; });6.2 使用变参模板实现策略组合templatetypename... Strategies class CombinedDiscount { private: std::tupleStrategies... strategies_; public: double applyDiscount(double price) { return applyImpl(price, std::index_sequence_forStrategies...{}); } private: templatestd::size_t... Is double applyImpl(double price, std::index_sequenceIs...) { return (std::getIs(strategies_).applyDiscount(price), ...); } }; // 使用示例 CombinedDiscountMemberDiscount, FestivalDiscount comboStrategy;7. 实际项目经验分享在电商系统的开发中我总结了以下策略模式的最佳实践策略命名使用行为Strategy的命名方式如PaymentStrategy、ShippingStrategy策略接口设计保持策略接口精简遵循单一职责原则默认策略提供合理的默认策略避免空策略导致的意外行为策略验证在设置新策略时进行参数验证线程安全多线程环境下要确保策略替换的原子性一个常见的坑是过度使用策略模式。曾经在一个项目中我们把每个小的行为变化都做成策略导致系统中有上百个小策略类维护起来反而更困难。后来我们通过以下方式优化合并相关的小策略对简单策略使用函数对象替代类建立策略的层次结构另一个实际经验是策略的序列化问题。当需要保存当前策略状态时可以考虑class SerializableStrategy : public DiscountStrategy { public: virtual std::string serialize() const 0; static std::unique_ptrSerializableStrategy deserialize(const std::string data); };对于需要频繁切换策略的高性能场景可以采用策略缓存池class StrategyPool { private: std::unordered_mapStrategyType, std::shared_ptrDiscountStrategy pool_; public: std::shared_ptrDiscountStrategy getStrategy(StrategyType type) { auto it pool_.find(type); if(it ! pool_.end()) return it-second; auto strategy createStrategy(type); pool_[type] strategy; return strategy; } };