105、23种设计模式之策略模式(14/23)

一、定义

策略模式(Strategy Pattern)是一种行为型设计模式,它通过定义一系列算法(策略),将每个算法封装成独立的类,并使它们可以相互替换。该模式允许算法在运行时动态切换,而无需修改客户端代码。其核心思想是将算法的变化与使用算法的上下文解耦。

二、优缺点

1、优点

(1)避免多重条件判断:消除冗长的if-else或switch-case语句,提高代码可读性。

(2)符合开闭原则:扩展新算法时无需修改现有代码,只需新增策略类。

(3)算法复用与隔离:每个策略类独立实现特定算法,便于维护和测试。

(4)动态切换算法:运行时可根据需求灵活更换算法。

2、缺点

(1)策略类膨胀:策略过多时,类数量显著增加,管理成本上升。

(2)客户端需感知策略:客户端必须了解所有策略类,可能违反迪米特法则(最少知识原则)。

(3)参数一致性要求:所有策略接口需保持参数一致,否则需额外适配。

三、应用场景

1、同类功能的多算法切换

  • 表单验证:邮箱、手机号、身份证等校验规则。
  • 数据导出:CSV、Excel、PDF格式导出。
  • 图表渲染:折线图、柱状图、饼图切换。

2、动态行为选择

  • 折扣计算:满减、折扣券、积分抵扣策略。
  • 权限校验:不同角色对应不同校验规则。

3、消除条件分支

  • 支付方式:信用卡、PayPal、比特币等支付策略。
  • 日志记录:文件、数据库、远程日志策略。

4、隐藏复杂算法

  • 路径规划:步行、驾车、公交导航策略。
  • 动画缓动:linear、ease-in、ease-out动画效果。

四、C# 示例代码

场景:实现不同出行方式的策略切换(开车、公交、自行车)。

csharp 复制代码
using System;

// 1. 定义策略接口
public interface ITravelStrategy
{
    void Travel();
}

// 2. 实现具体策略类
public class CarStrategy : ITravelStrategy
{
    public void Travel()
    {
        Console.WriteLine("乘坐汽车出行");
    }
}

public class BusStrategy : ITravelStrategy
{
    public void Travel()
    {
        Console.WriteLine("乘坐公交出行");
    }
}

public class BikeStrategy : ITravelStrategy
{
    public void Travel()
    {
        Console.WriteLine("骑自行车出行");
    }
}

// 3. 上下文类
public class TravelContext
{
    private ITravelStrategy _strategy;

    public TravelContext(ITravelStrategy strategy)
    {
        _strategy = strategy;
    }

    public void SetStrategy(ITravelStrategy strategy)
    {
        _strategy = strategy;
    }

    public void ExecuteTravel()
    {
        _strategy.Travel();
    }
}

// 4. 客户端代码
class Program
{
    static void Main()
    {
        // 初始策略:开车
        TravelContext context = new TravelContext(new CarStrategy());
        context.ExecuteTravel(); // 输出:乘坐汽车出行

        // 切换策略:公交
        context.SetStrategy(new BusStrategy());
        context.ExecuteTravel(); // 输出:乘坐公交出行

        // 切换策略:自行车
        context.SetStrategy(new BikeStrategy());
        context.ExecuteTravel(); // 输出:骑自行车出行
    }
}

五、关键点总结

1、策略接口设计

  • 定义统一的接口或抽象类,封装算法行为。
  • 确保所有具体策略类实现相同接口。

2、上下文类职责

  • 维护对策略对象的引用。
  • 提供方法动态切换策略(如SetStrategy)。
  • 委托策略对象执行具体行为(如ExecuteTravel)。

3、策略选择方式

  • 显式指定:客户端直接传入具体策略类。
  • 工厂模式:通过策略工厂类管理策略创建。
  • 依赖注入:结合Spring等框架自动注入策略(如C#的IServiceProvider)。

4、无状态策略优化

  • 将策略设计为无状态(纯函数),通过单例复用对象,减少内存开销。

5、命名规范

  • 策略类命名应清晰表达功能(如MobileValidationStrategy而非Strategy1)。

6、适用性判断

  • 适用场景:算法多样化且需动态切换。
  • 不适用场景:算法固定且数量少(直接使用if-else更简单)。

六、扩展建议

组合优于继承 :通过策略对象组合到上下文类,而非继承实现多态。
接口约束 :使用TypeScript等强类型语言明确策略接口。
性能优化:频繁创建策略对象时,考虑对象池缓存。

策略模式通过解耦算法与上下文,显著提升了代码的灵活性和可维护性,尤其适合算法频繁变化的场景。正确识别行为变化点并独立封装,是应用策略模式的关键。

相关推荐
回忆2012初秋3 小时前
工厂方法模式完整实现:GPS转换
设计模式·工厂方法模式
胡志辉的博客6 小时前
多智能体协作,不是多开几个 Agent:从中介者模式看 OpenClaw 和 Hermes Agent
人工智能·设计模式·ai·agent·中介者模式·openclaw·herman
shark22222226 小时前
能懂!基于Springboot的用户增删查改(三层设计模式)
spring boot·后端·设计模式
014-code7 小时前
日志规范:怎么写才不算写废话
java·开发语言·设计模式·日志
楼田莉子8 小时前
同步/异步日志系统:日志落地模块\日志器模块\异步日志模块
linux·服务器·c++·学习·设计模式
kyriewen1115 小时前
代码写成一锅粥?这5种设计模式让你的项目“起死回生”
前端·javascript·设计模式·typescript·ecmascript·html5
kyriewen15 小时前
代码写成一锅粥?这5种设计模式让你的项目“起死回生”
前端·javascript·设计模式
两年半的个人练习生^_^16 小时前
每日一学:设计模式之原型模式
java·开发语言·设计模式·原型模式
断眉的派大星1 天前
工厂模式(Factory Pattern)完整详解
python·设计模式
AI大法师1 天前
复盘 TikTok 品牌升级:动态品牌系统应该怎么理解和落地
大数据·人工智能·设计模式