# Extensibility

> Use when designing extensible architecture components using Adapter, Strategy, or Factory patterns based on explicit variability and coupling requirements.

- Skill: `sahilkhan30/extensibility` (Agent Skill)
- Install (CLI): `npx skillmds@latest add sahilkhan30/extensibility`
- Raw SKILL.md: https://api.skillmd.com/api/skills/sahilkhan30/extensibility/raw
- Safety review: pending
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: Coding & Dev Tools
- Author: SahilKhan30 (https://skillmd.com/u/sahilkhan30)
- Updated: 2026-09-21
- Page: https://skillmd.com/skills/sahilkhan30/extensibility

---


# Extensibility & Pattern Selection Skill

## Purpose
Guide appropriate application of software design patterns (**Adapter**, **Factory**, **Strategy**) based on requirements and trade-off analysis.

---

## 1. Pattern Selection Guidelines

### CONDITIONAL PATTERN APPLICABILITY

- **Adapter Pattern**:
  - *When to use*: Multiple external providers/channels expose incompatible interfaces and a stable internal domain abstraction reduces coupling.
  - *When NOT to use*: Only a single static interface exists with no planned alternative implementations.

- **Strategy Pattern**:
  - *When to use*: Business rules/algorithms (e.g. risk checks, fee calculations, matching rules) vary dynamically by product, type, or runtime metadata and need independent testability/replaceability.
  - *When NOT to use*: Business rules are static and uniform across all entities.

- **Factory / Registry Pattern**:
  - *When to use*: Runtime selection among multiple implementation instances (adapters or strategies) is required based on request metadata or configuration.
  - *When NOT to use*: Direct bean injection or single implementation suffices.

---

## 2. Reference Design Patterns

```java
// Adapter abstraction
public interface PaymentRailAdapter {
    RailType getSupportedRail();
    ProcessResult executePayment(PaymentRequest request);
}

// Strategy abstraction
public interface RiskAssessmentStrategy {
    String getStrategyName();
    RiskScore evaluate(TransactionContext context);
}

// Registry / Factory resolution
@Component
public class PaymentRailFactory {
    private final Map<RailType, PaymentRailAdapter> railMap;

    public PaymentRailFactory(List<PaymentRailAdapter> adapters) {
        this.railMap = adapters.stream()
            .collect(Collectors.toMap(PaymentRailAdapter::getSupportedRail, Function.identity()));
    }

    public PaymentRailAdapter getAdapter(RailType railType) {
        PaymentRailAdapter adapter = railMap.get(railType);
        if (adapter == null) throw new UnsupportedRailException(railType);
        return adapter;
    }
}
```

