策略模式

策略模式(Strategy Pattern)


定义

策略模式(Strategy Pattern)是行为型设计模式的一种,它‌定义算法家族并分别封装‌,使其可以‌相互替换‌,且算法的变化独立于使用它的客户端。该模式通过将算法与对象解耦来实现不同算法的灵活切换。

核心思想

  • 封装变化:将可能变化的算法部分独立出来。
  • 分离职责:将算法定义与使用解耦,避免代码中大量条件分支。
  • 面向接口编程‌:通过接口规范算法行为
  • 运行时动态切换‌:支持在程序执行期间灵活选择算法
  • 开闭原则实践‌:新增算法无需修改既有系统

模式结构

image
策略模式包含三个核心角色:

角色 职责说明
IStrategy 策略接口,声明所有支持的算法方法
ConcreteStrategy 具体策略实现类,实现接口定义的具体算法(至少包含两个不同实现)
Context 上下文类,持有策略引用,通过组合方式使用策略,提供策略修改接口

主要解决的问题

  • 消除条件分支‌:避免在代码中大量使用if-else或switch-case判断不同算法。
  • 算法复用困难‌:避免相似算法在多个类中重复实现
  • 灵活扩展算法‌:新增算法时无需修改原有代码,符合开闭原则。
  • 算法独立变化:不同算法可以独立演进,互不影响。

代码示例

场景:

电商系统根据不同促销策略计算订单折扣。

// 策略接口
public interface IDiscountStrategy
{
    decimal ApplyDiscount(decimal originalPrice);
}

// 具体策略实现
public class NoDiscount : IDiscountStrategy
{
    public decimal ApplyDiscount(decimal price) => price;
}

public class PercentageDiscount : IDiscountStrategy
{
    private readonly decimal _percentage;
    
    public PercentageDiscount(decimal percentage) => _percentage = percentage;

    public decimal ApplyDiscount(decimal price) => price * (1 - _percentage / 100);
}

public class CashRebate : IDiscountStrategy
{
    private readonly decimal _rebateAmount;
    
    public CashRebate(decimal amount) => _rebateAmount = amount;

    public decimal ApplyDiscount(decimal price) => Math.Max(0, price - _rebateAmount);
}

// 上下文类
public class PricingContext
{
    private IDiscountStrategy _strategy;
    
    public void SetStrategy(IDiscountStrategy strategy) => _strategy = strategy;
    
    public decimal CalculatePrice(decimal originalPrice)
    {
        return _strategy?.ApplyDiscount(originalPrice) ?? originalPrice;
    }
}

// 客户端调用
var context = new PricingContext();
var productPrice = 200.00m;

// 使用普通策略
context.SetStrategy(new NoDiscount());
Console.WriteLine($"原价: {context.CalculatePrice(productPrice):C}");

// 切换为8折策略
context.SetStrategy(new PercentageDiscount(20));
Console.WriteLine($"折扣价: {context.CalculatePrice(productPrice):C}");

// 切换为满减策略
context.SetStrategy(new CashRebate(50));
Console.WriteLine($"满减价: {context.CalculatePrice(productPrice):C}");

总结

优点

  • 解耦性强​​:算法与使用场景分离,便于独立维护。
  • ​​可扩展性高​​:新增策略无需修改现有代码。
  • ​​运行时灵活性​​:支持动态切换策略。

缺点​

  • ​​策略类数量增加​​:每个算法一个类,可能增加系统复杂度。
  • 客户端需了解策略差异​​:需要知道不同策略的区别以正确选择。

适用场景

  • 需要多种算法变体(如支付方式、排序算法、折扣规则)。
  • 需要动态切换算法。
  • 需要隐藏复杂算法实现细节。

​性能注意​

  • 若策略简单且数量少,直接使用条件判断可能更高效。
  • 对于频繁创建的策略对象,可结合工厂模式或享元模式优化。
posted @ 2025-04-27 10:48  刘继先  阅读(39)  评论(0)    收藏  举报