一、策略模式的核心思想

策略模式(Strategy Pattern)是一种行为型设计模式,其核心目标是将算法族封装成独立类,使它们能在运行时动态替换。通过该模式,客户端代码无需依赖具体算法实现,只需通过统一的接口调用,即可灵活切换不同策略,同时满足开闭原则(对扩展开放、对修改关闭)。

核心优势

  1. 解耦算法与业务逻辑:避免大量条件分支(如 if-else 或 switch),提升代码可维护性。
  2. 动态扩展性:新增策略只需添加新类,无需修改现有代码。
  3. 复用性与测试性:策略类可独立测试,且能被多个上下文复用。

二、策略模式的结构与角色
  1. IStrategy(策略接口)​
    定义所有算法的公共契约,例如 Execute() 或 Apply() 方法。
  2. ConcreteStrategy(具体策略)​
    实现接口的具体算法类(如 折扣策略A折扣策略B)。
  3. Context(上下文)​
    持有策略对象的引用,通过接口调用具体算法,支持运行时切换策略。

三、C# 实现示例:电商促销系统

假设电商平台需根据促销类型(无折扣、百分比折扣、固定金额折扣)计算订单价格。以下是代码实现:

1. 定义策略接口
// 促销策略接口
public interface IPromotionStrategy 
{
    decimal ApplyPromotion(decimal originalPrice);
}
2. 实现具体策略类
// 无折扣策略
public class NoDiscountStrategy : IPromotionStrategy 
{
    public decimal ApplyPromotion(decimal originalPrice) 
    {
        return originalPrice; // 原价
    }
}

// 百分比折扣策略
public class PercentageDiscountStrategy : IPromotionStrategy 
{
    private readonly decimal _discountPercentage;

    public PercentageDiscountStrategy(decimal discountPercentage) 
    {
        _discountPercentage = discountPercentage;
    }

    public decimal ApplyPromotion(decimal originalPrice) 
    {
        return originalPrice * (1 - _discountPercentage / 100);
    }
}

// 固定金额折扣策略
public class FixedAmountDiscountStrategy : IPromotionStrategy 
{
    private readonly decimal _discountAmount;

    public FixedAmountDiscountStrategy(decimal discountAmount) 
    {
        _discountAmount = discountAmount;
    }

    public decimal ApplyPromotion(decimal originalPrice) 
    {
        return originalPrice - _discountAmount;
    }
}
3. 上下文类(订单管理)
public class Order 
{
    private IPromotionStrategy _promotionStrategy;
    private decimal _originalPrice;

    public Order(decimal originalPrice, IPromotionStrategy promotionStrategy) 
    {
        _originalPrice = originalPrice;
        _promotionStrategy = promotionStrategy;
    }

    // 动态切换策略
    public void SetPromotionStrategy(IPromotionStrategy promotionStrategy) 
    {
        _promotionStrategy = promotionStrategy;
    }

    public decimal CalculateFinalPrice() 
    {
        return _promotionStrategy.ApplyPromotion(_originalPrice);
    }
}
4. 客户端调用
var order = new Order(100.0m, new NoDiscountStrategy());
Console.WriteLine($"无折扣价格:{order.CalculateFinalPrice()}"); // 输出:100.0

order.SetPromotionStrategy(new PercentageDiscountStrategy(20)); // 20%折扣
Console.WriteLine($"百分比折扣价格:{order.CalculateFinalPrice()}"); // 输出:80.0

order.SetPromotionStrategy(new FixedAmountDiscountStrategy(30)); // 固定减30
Console.WriteLine($"固定金额折扣价格:{order.CalculateFinalPrice()}"); // 输出:70.0

四、策略模式的高级应用场景
  1. 与工厂模式结合
    通过工厂类根据条件动态创建策略对象(如根据用户类型选择优惠策略)。
  2. 依赖注入(DI)​
    在 ASP.NET Core 中,通过依赖注入容器注册策略,实现自动切换(如 services.AddTransient<IPromotionStrategy, PercentageDiscountStrategy>())。
  3. Lambda 表达式简化
    使用委托(Delegate)替代接口,减少类定义(适用于简单策略)
    public class Calculator 
    {
        public decimal Calculate(Func<decimal, decimal> strategy, decimal price) 
        {
            return strategy(price);
        }
    }
    // 调用示例
    var result = new Calculator().Calculate(p => p * 0.8m, 100.0m); // 直接传递Lambda

五、策略模式与相似模式对比
  1. 状态模式
    • 策略模式:客户端主动选择算法。
    • 状态模式:状态自动切换行为(如订单状态流转)。
  2. 装饰器模式
    • 策略模式:替换整个算法。
    • 装饰器模式:叠加附加功能(如日志+缓存)。

六、优缺点总结

优点

  • 消除条件分支,提升代码可读性。
  • 支持动态扩展,符合单一职责原则。

缺点

  • 类数量可能激增(每个策略对应一个类)。
  • 客户端需理解策略差异,增加使用成本。

七、实际案例扩展
  1. 支付网关选择
    根据用户地理位置动态切换支付方式(如支付宝、PayPal)。
  2. 图像处理算法
    支持多种压缩算法(JPEG、PNG)的运行时切换。
  3. 游戏AI行为
    根据敌人类型切换攻击策略(如近战、远程)。

八、总结

策略模式通过算法封装与动态替换,为复杂业务逻辑提供了优雅的解决方案。在C#中,其实现灵活且易于集成至现代框架(如依赖注入)。无论是电商促销、支付系统还是游戏开发,合理运用策略模式均可显著提升代码质量与可维护性。

更多推荐