Apply Creational Patterns
Overview
Create objects without hard-coding concrete classes into callers. Use these patterns to isolate construction, support multiple variants, and keep object creation testable.
A note on scope: these guidelines assume systemic TypeScript (long‑lived apps/services). For short‑lived scripts, you can simplify (inline construction, fewer layers) as long as tests and change-cost stay acceptable.
Workflow
- •Decide “scriptic vs systemic” and set policies (boundary decoding, error semantics, ownership/lifetimes).
- •Identify the creation pressure: variant explosion, complex setup, environment wiring, or lifecycle constraints.
- •Decide what must be stable for callers (interface and invariants), and what may vary (implementation, configuration, dependencies).
- •Pick the smallest creational pattern that matches the pressure (see chooser).
- •Implement with DI-friendly constructors or factory functions; keep creation as pure as possible.
- •Add tests that assert:
- •correct type selection for each variant
- •invariants validated during creation
- •callers depend only on interfaces/abstractions
Chooser
- •Factory Method: subclasses/modules decide which product to create for a common interface.
- •Abstract Factory: select a “family” (e.g., platform/vendor) and create compatible products together.
- •Builder: stepwise construction with validation; many optional parts or multiple representations.
- •Prototype: clone existing instances to avoid complex constructors; preserve runtime types.
- •Singleton (caution): one instance truly required; prefer passing dependencies explicitly or container-managed singletons.
Implementation Checklist
- •Make factories return interfaces/abstract types; hide concrete constructors in one place.
- •Keep variant selection logic near configuration boundaries (composition root).
- •Avoid “stringly-typed factories”; use typed keys (
as constmaps / unions) where possible. - •Validate invariants at creation time; fail fast with actionable errors.
- •Avoid import-time wiring in systemic code; create/wire dependencies in a composition root so lifetimes are explicit.
- •If created objects own resources, make lifetimes explicit (
start/stop/dispose) and define ownership (who shuts it down). - •Keep object graphs shallow in tests by injecting fakes/mocks (avoid global state).
Snippets (optional)
- •TypeScript:
references/snippets/typescript.md - •React:
references/snippets/react.md
References
Read the relevant reference file before implementing or refactoring toward the pattern:
- •
references/factory-method.md - •
references/abstract-factory.md - •
references/builder.md - •
references/prototype.md - •
references/singleton.md
Each reference includes: selection cues, minimal structure, pitfalls, and test ideas.
Output Template
When applying a creational pattern, return:
- •The creation pressure (variants/complex setup/lifecycle constraints) and what must stay stable for callers.
- •The chosen pattern and the proposed seam (factory/builder/prototype) + wiring point (composition root).
- •Verification steps (tests for variant selection, invariant validation, and lifetime ownership).