Token导航 LogoToken导航

Agent Skill · 效率

bookforge-strategy-pattern-implementor(Bookforge 策略模式实施者)

bookforge-strategy-pattern-implementor 用于处理 GitHub 仓库、Issue、Pull Request 和代码协作信息,适合在 OpenClaw 中需要围绕仓库状态、代码变更或协作事项进行整理时使用。可结合来源仓库、安装命令和原始 README 继续核验具体用法。安装前建议确认权限范围、维护状态,以及是否会触发联网、命令执行或文件读写。

bookforge-strategy-pattern-implementor 是效率类 Agent Skill,可用宿主为 OpenClaw,通过ClawHub获取,权限为调用外部服务;许可证为 MIT-0,第三方扫描已通过,按安装量在效率类的 21,003 个 Skill 里排第 15,448。

总安装 3,109周安装 127GitHub Stars 公开资料未说明下载 1,006核验 2026-05-01

安装说明

本站只整理中文说明,不托管安装包,也不代用户安装。
GitHub
许可证
MIT-0
版本
1.0.0

安装方式

通过对话安装

复制提示词发给支持本地命令或 Skills 的 AI 助手,先确认命令和权限,再让它执行。

请帮我安装这个 Agent Skill:bookforge-strategy-pattern-implementor(Bookforge 策略模式实施者)
来源仓库:https://github.com/quochungto/bookforge-strategy-pattern-implementor
安装命令:
openclaw skills install bookforge-strategy-pattern-implementor
安装前请先检查当前环境是否支持对应 CLI,并向我确认将要执行的命令、安装目录、联网范围和文件读写权限;确认后再执行。

命令行安装

复制命令到本机终端执行。该命令会通过 OpenClaw 从第三方来源获取 Skill;本站只展示命令,不托管安装包,也不自动执行。

ClawHubOpenClaw
openclaw skills install bookforge-strategy-pattern-implementor

这个 Skill 是做什么的

效率类 Skill 把重复的整理、汇总、转换工作交给助手完成,减少手工复制粘贴。

封装可互换算法为统一接口实现策略模式。简化条件分支逻辑提升代码可扩展性。适用于行为动态变化的系统设计场景。作为 OpenClaw 的效率类技能提供代码辅助。需配合具体语言规范实现细节调整。bookforge-strategy-pattern-implementor 属于效率类 Skill,可作为该场景下的辅助能力补充。

上手步骤

4 步
  1. 1

    确认自己的宿主工具

    公开资料标注支持 OpenClaw;先确认自己用的是其中之一,再按对应工具的 Skills 目录放置。

  2. 2

    拿到安装命令

    可以直接复制的命令是 openclaw skills install bookforge-strategy-pattern-implementor;命令里的占位符换成自己的路径或密钥再执行。

  3. 3

    安装后重启宿主

    命令执行完要完全退出宿主工具再打开,让新装的 Skill 被重新扫描到,否则列表里可能看不到。

  4. 4

    按最小权限试用

    它需要调用外部服务,先在测试目录或测试账号里跑,确认没问题再放到正式项目。

常见问题

6 条

bookforge-strategy-pattern-implementor 怎么安装?

在终端执行 openclaw skills install bookforge-strategy-pattern-implementor。装完完全退出宿主工具再打开,让它重新扫描本地 Skill。

bookforge-strategy-pattern-implementor 支持哪些 AI 工具?

公开资料标注支持 OpenClaw。其他工具只要能读取本地 Skill 目录,一般也能手动放进去,但要自己确认触发方式是否一致。

bookforge-strategy-pattern-implementor 需要什么权限?

权限级别是调用外部服务。该 Skill 可能调用第三方服务、云服务或外部模型 API,使用前需要确认账号、额度、数据发送范围和服务条款。

bookforge-strategy-pattern-implementor 是免费的吗?

来源标注的许可证是 MIT-0。本站不代收任何费用,也不托管安装包;能否商用、要不要署名,以许可证原文为准。

bookforge-strategy-pattern-implementor 用的人多吗?

公开数据是累计安装 3,109 次,近一周安装 127 次,下载 1,006 次。这些数字来自第三方目录统计,只能当作热度参考,不代表质量或安全性。

bookforge-strategy-pattern-implementor 安全吗?

第三方扫描结果为通过,但这只覆盖已知的静态检查项,不能替代自己读一遍源码和安装命令。

值得选的地方和要先想清楚的地方

值得选的地方

  • 专注 OpenClaw 一种宿主,触发方式和使用习惯不用来回切换。
  • 许可证明确为 MIT-0,商用和分发边界好判断。
  • 第三方扫描已通过,常见的高风险行为没有命中。

先想清楚的地方

  • 第三方目录整理,版本更新和行为细节以来源仓库为准。

适不适合你

更适合

  • 已经在用 OpenClaw,想直接扩展它能力的人。
  • 需要处理效率类任务、又不想每次都手写提示词的人。
  • 需要许可证清楚、并且有第三方扫描结果的团队项目。

不太适合

  • 需要厂商级技术支持和 SLA 的生产系统。

效率类 Skill 对比

6 个同类
Skill总安装GitHub 星权限许可证扫描
github

GitHub 代码协作 · OpenClaw

7,632,918545需要联网MIT-0通过
nano-pdf

Nano PDF 文档 · OpenClaw

4,249,476231需要联网MIT-0通过
auto-updater

自动更新程序 · OpenClaw

2,964,063386操作浏览器MIT-0通过
video-frames

视频帧 · OpenClaw

2,621,304112需要联网MIT-0通过
gemini

Gemini 助手 · OpenClaw

2,547,39648需要联网MIT-0有提醒
bookforge-strategy-pattern-implementor

Bookforge 策略模式实施者 · 本页

3,109—调用外部服务MIT-0通过

按安装量取同分类前几名;数字来自第三方目录统计,只作热度参考,不代表质量结论。

SKILL.md 原文

name
strategy-pattern-implementor
description
|
version
1.0.0
homepage
https://github.com/bookforge-ai/bookforge-skills/tree/main/books/design-patterns-gof/skills/strategy-pattern-implementor
metadata
{"openclaw":{"emoji":"📚","homepage":"https://github.com/bookforge-ai/bookforge-skills"}}
status
draft
depends-on
source-books
title
Design Patterns: Elements of Reusable Object-Oriented Software
authors
["Erich Gamma", "Richard Helm", "Ralph Johnson", "John Vlissides"]
chapters
[5]
pages
[48-50, 292-300]
tags
[design-patterns, behavioral, gof, strategy, refactoring, algorithms, composition]
execution
tier
2
mode
full
inputs
description
Existing code with conditional branches selecting between algorithm variants, or a description of the algorithmic variation that needs encapsulation
tools-required
[TodoWrite, Read]
tools-optional
[Grep, Edit]
mcps-required
[]
environment
Any codebase. Language-agnostic — examples use Python but the pattern applies universally.

Strategy Pattern Implementor

When to Use

You have a class that selects between algorithm variants and need to refactor it so algorithms can vary independently from the clients that use them. This skill applies when:

  • A class contains switch statements or if/else chains that select between behavioral variants — the primary code smell
  • Multiple related classes differ only in their behavior (same structure, different computation)
  • You need different space-time trade-offs for the same operation (fast-and-approximate vs. slow-and-precise)
  • An algorithm uses data clients should not know about (complex internal data structures that would leak through the interface)
  • You need to swap the algorithm at runtime without changing the client

Before starting, confirm:

  • Is this a client-selected algorithm switch (Strategy) rather than an object self-transitioning based on internal state (State)? If unsure, use behavioral-pattern-selector first.
  • Does the variation belong in the class itself, or is it better expressed via a superclass skeleton with subclass steps (Template Method via inheritance)? Strategy uses composition — the algorithm is a separate object, not a subclass.

Process

Step 1: Set Up Tracking and Identify the Conditional

ACTION: Use TodoWrite to track progress, then locate the conditional code that signals the need for Strategy.

WHY: The conditional block is the concrete artifact you are eliminating. Identifying it precisely — its location, what it selects between, and what data it touches — drives every subsequent decision about interface design and data passing. Without pinning this down first, the refactoring risks producing a Strategy structure that does not fit the actual variation.

TodoWrite:
- [ ] Step 1: Locate the conditional and characterize the variation
- [ ] Step 2: Define the Strategy interface
- [ ] Step 3: Implement ConcreteStrategy classes
- [ ] Step 4: Refactor the Context class
- [ ] Step 5: Validate and apply optional optimizations

Locate the conditional using Read or Grep, then document:

ElementWhat to capture
LocationFile, class, method where the conditional lives
VariantsHow many branches? What does each compute?
Data requiredWhat data does each branch use from the context?
Selection pointWho chooses the variant — the caller, a config value, or a runtime condition?
Change frequencyHow often are new variants added? Does this class change every time?

If working from a description rather than existing code, draft a minimal "before" sketch showing the conditional structure.


Step 2: Define the Strategy Interface

ACTION: Design the abstract Strategy interface — the single method (or small set of methods) that all ConcreteStrategies must implement.

WHY: The Strategy interface is the contract that decouples the Context from all algorithm implementations. If it is too narrow (missing data the strategy needs), ConcreteStrategies will have to reach into the Context through back-channels, increasing coupling. If it is too wide (exposing data no strategy uses), the communication overhead between Strategy and Context grows. The interface must be general enough that you will not have to change it when adding new ConcreteStrategies — this is the central design decision of the pattern.

Two data-passing approaches — choose one:

ApproachHow it worksWhen to prefer
Take data to the strategyContext passes all needed data as parameters to the strategy methodAlgorithm needs a bounded, well-known set of inputs; keeps Strategy and Context decoupled
Pass context as argumentStrategy receives the Context object itself and requests what it needsAlgorithm needs variable or large amounts of context data; reduces parameter proliferation but couples Strategy to Context's interface

Design the interface method signature:

# Approach 1: explicit parameters (preferred when data set is bounded)
class SortStrategy:
    def sort(self, data: list) -> list:
        raise NotImplementedError

# Approach 2: context reference
class SortStrategy:
    def sort(self, context: "Sorter") -> None:
        raise NotImplementedError

Check: Will a new ConcreteStrategy ever need data this interface does not provide? If yes, revise — you should not need to change the interface when adding strategies.


Step 3: Implement ConcreteStrategy Classes

ACTION: Extract each conditional branch into its own ConcreteStrategy class that implements the Strategy interface.

WHY: Each branch in the original conditional is an independently varying algorithm. Making each one a class gives it a name (making the code self-documenting), an isolated scope for its data structures (preventing algorithm-specific complexity from polluting the Context), and a testable boundary (each strategy can be tested in isolation without instantiating the full Context).

For each branch in the original conditional:

  1. Create a class named after the algorithm it encapsulates (not after what it replaces — use domain terminology, e.g., BubbleSortStrategy, not OldSortBranch)
  2. Implement the interface method with the branch's logic
  3. Move any algorithm-specific private data into the ConcreteStrategy (not the Context)
class BubbleSortStrategy(SortStrategy):
    """Simple sort — O(n²), stable, no extra memory."""
    def sort(self, data: list) -> list:
        result = data[:]
        n = len(result)
        for i in range(n):
            for j in range(0, n - i - 1):
                if result[j] > result[j + 1]:
                    result[j], result[j + 1] = result[j + 1], result[j]
        return result

class QuickSortStrategy(SortStrategy):
    """Fast sort — O(n log n) average, not stable, in-place."""
    def sort(self, data: list) -> list:
        result = data[:]
        self._quicksort(result, 0, len(result) - 1)
        return result

    def _quicksort(self, arr, low, high):
        if low < high:
            pi = self._partition(arr, low, high)
            self._quicksort(arr, low, pi - 1)
            self._quicksort(arr, pi + 1, high)

    def _partition(self, arr, low, high):
        pivot = arr[high]
        i = low - 1
        for j in range(low, high):
            if arr[j] <= pivot:
                i += 1
                arr[i], arr[j] = arr[j], arr[i]
        arr[i + 1], arr[high] = arr[high], arr[i + 1]
        return i + 1

Stateless strategies as Flyweights: If a ConcreteStrategy holds no instance state (all data comes from parameters), it can be shared across multiple Context instances. A single shared instance replaces per-context allocation. This optimization applies when strategies are lightweight and stateless — do not force it if the strategy needs per-invocation state.


Step 4: Refactor the Context Class

ACTION: Replace the conditional in the Context with a reference to a Strategy object and a delegation call.

WHY: This is the core structural change. The Context no longer *knows* how to perform the algorithm — it only knows *that* an algorithm exists and how to invoke it. The conditional disappears entirely, replaced by a single delegation call. The Context becomes open to extension (new strategies) without modification, satisfying the open-closed principle.

Refactoring steps:

  1. Add a strategy attribute (initialized via constructor or setter)
  2. Replace the entire conditional block with a single call to self.strategy.algorithm_method(...)
  3. Remove any algorithm-specific data that has moved into ConcreteStrategy classes
  4. Optionally provide a default strategy so clients that do not care about the choice are unaffected
# BEFORE (conditional in Context)
class DataProcessor:
    def __init__(self, algorithm: str):
        self._algorithm = algorithm

    def process(self, data: list) -> list:
        if self._algorithm == "bubble":
            # bubble sort logic — 10 lines
            ...
        elif self._algorithm == "quick":
            # quicksort logic — 20 lines
            ...
        elif self._algorithm == "merge":
            # merge sort logic — 25 lines
            ...

# AFTER (Strategy delegation)
class DataProcessor:
    def __init__(self, strategy: SortStrategy = None):
        # Default strategy makes Strategy optional for clients
        self._strategy = strategy or BubbleSortStrategy()

    def set_strategy(self, strategy: SortStrategy) -> None:
        """Swap algorithm at runtime without reconstructing the context."""
        self._strategy = strategy

    def process(self, data: list) -> list:
        return self._strategy.sort(data)

Making Strategy optional: If it is meaningful for the Context to have no strategy, check before delegating and execute default behavior when none is set. This keeps clients that do not need strategy selection from having to deal with Strategy objects at all.


Step 5: Validate and Apply Optional Optimizations

ACTION: Verify the refactoring is complete, then apply optimizations if warranted.

WHY: The refactoring is only complete when the original conditional is fully gone and all variants are covered. Partial migration — leaving one branch in the Context "for now" — defeats the pattern and re-introduces the code smell. Validation catches this before new code is written against the incomplete structure.

Validation checklist:

  • [ ] The original conditional block is entirely removed from the Context
  • [ ] Every branch of the original conditional has a corresponding ConcreteStrategy
  • [ ] The Context delegates to the strategy via the interface — it imports no ConcreteStrategy class directly
  • [ ] Each ConcreteStrategy can be instantiated and tested independently
  • [ ] Adding a new algorithm requires only a new class, not a change to the Context

Optional optimizations:

OptimizationWhen to apply
Flyweight sharingConcreteStrategies are stateless — share one instance across all Contexts instead of allocating per-Context
Default strategyMost clients use one algorithm — set it as default so callers who do not care are unaffected
Factory for selectionStrategy selection logic is complex — extract it into a factory rather than leaving it scattered in callers
Abstract base with shared logicMultiple ConcreteStrategies share common steps — add a base ConcreteStrategy class with shared implementation (not the interface)

Drawback awareness — address before finishing:

  • Client awareness: Clients must now know which ConcreteStrategy to instantiate. If this knowledge is non-trivial (depends on configuration, environment, or runtime data), introduce a factory or builder to centralize selection logic.
  • Communication overhead: The Strategy interface is shared by all ConcreteStrategies regardless of complexity. Simple strategies may receive parameters they do not use (e.g., ArrayCompositor in the Lexi case ignores stretchability data). If this overhead is significant, consider tighter coupling between specific strategies and the context — but accept that this reduces generality.

Examples

Example 1: Payment Processing (Classic Conditional to Strategy)

Scenario: An e-commerce checkout has a PaymentService with a large if/else chain selecting between credit card, PayPal, and bank transfer logic. A new payment method is requested every quarter, and each addition requires modifying PaymentService directly.

Trigger: "Every time we add a payment provider, we touch the same process_payment method and it keeps growing."

Before (the code smell):

class PaymentService:
    def process_payment(self, amount: float, method: str, details: dict):
        if method == "credit_card":
            # validate card, charge via Stripe, handle 3DS...
        elif method == "paypal":
            # OAuth flow, PayPal API call, webhook...
        elif method == "bank_transfer":
            # IBAN validation, SEPA/ACH routing...
        else:
            raise ValueError(f"Unknown method: {method}")

After (Strategy):

class PaymentStrategy:
    def process(self, amount: float, details: dict) -> PaymentResult:
        raise NotImplementedError

class CreditCardStrategy(PaymentStrategy):
    def process(self, amount: float, details: dict) -> PaymentResult:
        # Stripe integration, 3DS, card validation

class PayPalStrategy(PaymentStrategy):
    def process(self, amount: float, details: dict) -> PaymentResult:
        # OAuth, PayPal API, webhook handling

class BankTransferStrategy(PaymentStrategy):
    def process(self, amount: float, details: dict) -> PaymentResult:
        # IBAN validation, SEPA/ACH routing

class PaymentService:
    def __init__(self, strategy: PaymentStrategy):
        self._strategy = strategy

    def process_payment(self, amount: float, details: dict) -> PaymentResult:
        return self._strategy.process(amount, details)

# Caller selects the strategy — PaymentService never changes
service = PaymentService(CreditCardStrategy())
result = service.process_payment(99.99, {"card_number": "..."})

Output: PaymentService is closed to modification. Adding CryptoStrategy requires zero changes to existing code.


Example 2: Lexi Document Formatter (GoF Case Study)

Scenario: Lexi, a WYSIWYG document editor, must break text into lines. Several algorithms exist: a simple greedy line-breaker, a full TeX-quality algorithm optimizing paragraph-level color, and a fixed-interval breaker for icon grids. The algorithms have different speed-quality trade-offs and the user may switch between them.

Trigger: "The formatting algorithm needs to change at runtime depending on document type, and we need to add new algorithms without touching the document structure."

Design (from GoF, pages 48-50 and 296-298):

Context:     Composition  (holds content glyphs, line width)
Strategy:    Compositor   (abstract — Compose() interface)
ConcreteA:   SimpleCompositor    — greedy, line-at-a-time, fast
ConcreteB:   TeXCompositor       — paragraph-at-a-time, optimizes whitespace color
ConcreteC:   ArrayCompositor     — fixed interval, for icon grids

The Compositor interface takes all layout data as explicit parameters (Approach 1 — data to the strategy):

virtual int Compose(
    Coord natural[], Coord stretch[], Coord shrink[],
    int componentCount, int lineWidth, int breaks[]
) = 0;

This interface is wide enough to support all three algorithms. SimpleCompositor ignores stretchability; ArrayCompositor ignores everything except component count. This is the communication overhead trade-off — some ConcreteStrategies receive data they do not use. The GoF accept this because the alternative (passing this as a context reference) would couple Compositor subclasses to Composition's full interface.

Runtime swap:

// Switching quality at runtime — no reconstruction of Composition
composition->SetCompositor(new TeXCompositor());
composition->Repair();  // delegates to compositor->Compose(...)

Output: Adding a new linebreaking algorithm is a new Compositor subclass. Neither Composition nor the glyph classes are ever modified.


Example 3: Report Exporter with Runtime Selection

Scenario: A reporting tool exports data as CSV, JSON, or PDF. The format is determined by user selection at runtime. Currently the export logic lives in a single export() method with a format string parameter driving a conditional.

Trigger: "Users can choose the export format from a dropdown — the format isn't known until they click Export."

Strategy interface (data to strategy, Approach 1):

class ExportStrategy:
    def export(self, records: list[dict], output_path: str) -> None:
        raise NotImplementedError

class CsvExportStrategy(ExportStrategy):
    def export(self, records, output_path):
        import csv
        with open(output_path, "w", newline="") as f:
            writer = csv.DictWriter(f, fieldnames=records[0].keys())
            writer.writeheader()
            writer.writerows(records)

class JsonExportStrategy(ExportStrategy):
    def export(self, records, output_path):
        import json
        with open(output_path, "w") as f:
            json.dump(records, f, indent=2)

class PdfExportStrategy(ExportStrategy):
    def export(self, records, output_path):
        # reportlab or weasyprint integration
        ...

class ReportExporter:
    _STRATEGIES = {
        "csv": CsvExportStrategy,
        "json": JsonExportStrategy,
        "pdf": PdfExportStrategy,
    }

    def __init__(self):
        self._strategy: ExportStrategy = CsvExportStrategy()  # default

    def set_format(self, format_key: str) -> None:
        """Runtime swap — called when user selects format in UI."""
        cls = self._STRATEGIES.get(format_key)
        if not cls:
            raise ValueError(f"Unknown format: {format_key}")
        self._strategy = cls()

    def export(self, records: list[dict], output_path: str) -> None:
        self._strategy.export(records, output_path)

Key decision: The _STRATEGIES registry centralizes selection logic in the Context, keeping callers simple. An alternative is to move this registry to a factory, which is preferable when selection logic becomes complex (e.g., involving feature flags or user tier).

Output: The UI dropdown maps to set_format(). Adding XML export is a new XmlExportStrategy class plus one entry in _STRATEGIES — the rest of the system is unchanged.


Strategy vs. Template Method — When to Use Which

Both patterns encapsulate algorithmic variation. The choice is composition vs. inheritance:

DimensionStrategyTemplate Method
MechanismComposition — context holds a strategy objectInheritance — subclass overrides abstract steps
Runtime swapYes — install a different strategy objectNo — fixed at class definition
GranularityEntire algorithm is replacedOnly specific steps are replaced; skeleton is fixed
Class countOne class per algorithm variantOne subclass per algorithm variant
CouplingStrategy and Context are loosely coupledSubclass is tightly coupled to superclass skeleton
Evolution pathStart with Template Method → migrate to Strategy when inheritance becomes limiting—

Choose Strategy when the algorithm must be swappable at runtime, when you do not control the class hierarchy, or when the number of variants is large and growing.

Choose Template Method when the algorithm skeleton is fixed and only specific steps vary, and when compile-time binding is acceptable.


Reference Files

FileContents
references/strategy-implementation-guide.mdParticipants, full consequences catalog, interface design decision tree, Flyweight optimization, language-specific notes

License

This skill is licensed under CC-BY-SA-4.0. Source: BookForge — Design Patterns: Elements of Reusable Object-Oriented Software by Erich Gamma, Richard Helm, Ralph Johnson, John Vlissides.

Related BookForge Skills

Install related skills from ClawhHub:

  • clawhub install bookforge-behavioral-pattern-selector

Or install the full book set from GitHub: bookforge-skills

平台分布

OpenClaw

83.7%
按下载量换算842

安全审计

VirusTotal

通过

ClawScan

通过

Static analysis

通过

权限和风险

调用外部服务

该 Skill 可能调用第三方服务、云服务或外部模型 API,使用前需要确认账号、额度、数据发送范围和服务条款。

安装前确认

本站仅展示第三方公开信息,不托管安装包,不提供自动安装或运行环境。安装前应自行审查源码、依赖和命令行为。目前只有一个公开来源,建议同时核对源仓库。

继续浏览同类 Skills