mcpField
G
gof-strategy

gof-strategy

github.com/yonatankarp开发143 次安装23 周前更新
代码仓库

关于 gof-strategy

为需要在多种算法间选择的开发者讲解策略设计模式,涵盖如何通过共同接口封装行为,以及何时不值得引入这层间接结构。

主要功能

  1. 01封装不同算法
  2. 02通过接口委托行为
  3. 03在运行时替换策略
  4. 04区分策略与相关模式

适用场景

  1. 01替换基于类型的算法分支
  2. 02无需大量子类即可改变行为
  3. 03有明确需求时增加第二种算法

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/yonatankarp/software-design-skills --skill gof-strategy

安装后在 Claude Code 中输入/gof-strategy确认已加载。

详细介绍

一句话概述

将一系列相关算法分别封装在统一接口之后,让客户端在运行时组合所需的算法,而不是硬编码算法或根据类型标记进行分支判断。

何时使用此技能

  • 类中有针对“类型”字段的 switch/if 分支,用于在不同算法之间进行选择(排序顺序、定价规则、验证策略)。
  • 为改变某一项行为而使用子类,导致类的数量呈组合式膨胀。
  • 预计算法集会不断扩展。
  • 两个类的大部分行为相同,但在某个单一维度上有所不同(例如,MallardDuck 和 RubberDuck 的区别仅在于它们如何叫、如何飞)。

何时不使用此技能

  • 只有一种算法,也看不到近期会有第二种算法的迹象——增加间接层不符合 YAGNI 原则。
  • 变化的行为涉及一系列步骤,但这些步骤的结构大多相同——这适用于 gof-template-method。
  • 变化的是组合什么,而不是如何计算——这通常适用于 gof-decorator。

核心内容

策略模式将客户端要做什么与客户端如何做到解耦。客户端通过一个小型接口持有策略对象的引用;具体策略在构造时注入(也可以通过 setter 在运行时更改)。

组合优于继承:与其通过子类重写某个方法,不如注入一个负责该方法的小型对象。每种策略都可以独立测试,也可以在不修改宿主对象的情况下替换。

伪结构:

  • 定义接口 Strategy { operate(input) }。
  • 具体策略实现该接口:StrategyA、StrategyB 等。
  • 上下文类持有一个 Strategy 并委托调用:context.do(input) { strategy.operate(input) }。

判断启发

  • 当你现在确实有 ≥2 种算法,或现在有一种算法且有充分、近期会实现第二种算法的理由时,使用此模式。
  • 与其让每种算法都对应一个子类并导致类数量膨胀,不如优先采用策略模式。
  • 如果策略无状态,可以使用 object 实例(单例),而不必为每个上下文都分配实例。

反模式

  • 仅仅“以防将来需要更多算法”就为单一算法引入策略模式——间接层的成本立刻显现,而收益可能永远不会出现。
  • 策略对象携带过多状态——策略模式旨在封装行为;如果策略携带大量按调用变化的状态,应重新考虑职责边界。
  • 按策略的实现方式命名(FastSortStrategy、SlowSortStrategy),而不是按其在领域中的含义命名(PriorityFirstSort、ChronologicalSort)。

另请参阅

  • gof-state —— 结构相同,意图不同(策略模式改变计算内容;状态模式改变对象生命周期中的行为)。
  • gof-template-method —— 当变化的是算法中的步骤,而不是整个算法时使用。
  • gof-command —— 用于参数化操作,而不是算法。
  • gof-kotlin-idioms —— 在 Kotlin 中,策略通常只是一个函数类型参数 (T) -> R;无需接口。

参考资料

  • Head First Design Patterns(第 2 版),第 1 章(“欢迎来到设计模式”)——经典的策略模式章节,以鸭子模拟器为例进行讲解。

评论

支持 Markdown