Skills DirectorySkills Directory
SkillsLearnSecurityCategoriesDocsCommunityBlog
Sign InSubmit Skill
Skills Directory

Security-tested agent skills for Claude, coding agents, and AI workflows.

Directory

  • Browse Skills
  • All Skills A–Z
  • Claude Skills
  • Claude Code Skills
  • Agent Skills
  • Categories
  • Submit a Skill

Learn

  • Learn Hub
  • Install Claude Skills
  • Write SKILL.md
  • Skills vs MCP
  • Directories Compared

Security

  • Security
  • Methodology
  • Secure Claude Skills
  • Security Badges

Company

  • About
  • Community
  • Blog
  • API Docs
  • Advertise

2026 Skills Directory. All rights reserved.

Back to skills

Gof Abstract Factory

ASecurity

Abstract Factory in modern Java: the pattern exists to keep a _family_ of related objects mutually consistent when the family varies, not to centralise construction. Covers the family invariant that justifies it, when existing composition resolves the deployment-time case, when per-request or per-tenant selection benefits from a family provider, and how to express it as a record of suppliers or a sealed provider rather than a four-level interface hierarchy. Use when a factory interface is pro...

2 stars
0 votes
0 copies
0 views
Added 9/19/2026
developmentrustgojavaexpressspringtestinggitapiperformance

Works with

cliapi

Security Analysis

A100/100

Scanned 9/19/2026

Install to Claude Code

$npx -y skills add robsonkades/agent-skills --skill gof-abstract-factory --agent claude-code

Installs into .claude/skills of the current project.

Are you the author of Gof Abstract Factory?

Add the live security badge to your README — it updates automatically with every re-scan.

Security grade badge for Gof Abstract Factory
[![Security: A — Skills Directory](https://www.skillsdirectory.com/api/skills/robsonkades-gof-abstract-factory/badge)](https://www.skillsdirectory.com/skills/robsonkades-gof-abstract-factory)

More formats (shields.io, HTML) on the badges page.

Download Zip
Files
SKILL.md
---
name: gof-abstract-factory
description: >
  Abstract Factory in modern Java: the pattern exists to keep a _family_ of related objects
  mutually consistent when the family varies, not to centralise construction. Covers the family
  invariant that justifies it, when existing composition resolves the deployment-time
  case, when per-request or per-tenant selection benefits from a family provider, and how to
  express it as a record of suppliers or a sealed provider rather than a four-level interface
  hierarchy. Use when a factory interface is proposed, when profile-specific object graphs are
  being built by hand, when a family of parser/renderer/validator types must never be mixed
  across formats, when a plugin SPI must supply several related types at once, or when reviewing
  a factory whose products have nothing to do with each other. Does not cover subclass creation
  hooks (gof-factory-method), assembling one complex object (gof-builder), copying an
  existing instance (gof-prototype), or wiring policy in general (java-dependency-inversion).
---

# Abstract Factory

## Purpose

Select related products together and preserve their compatibility. Abstract Factory alone does
not make mixing impossible: callers can combine products from different factories, and a public
aggregate constructor can accept mismatched products. State the enforcement boundary: trusted
assembly with contract tests, validated family identities, family-typed APIs, or encapsulated
operations that never expose mixable products. Shared family identity may also require the same
transaction/session instance, not merely the same vendor or format.

If there is no invariant binding the products to each other, this is not Abstract Factory. It
is a bag of factory methods, and it should be several separate providers or none at all.

Start with ordinary consumer calls, a relevant advanced use (such as a plugin or session-owned
family), and likely misuse. Inspect callers, wiring, supported keys and resource ownership before
asking about missing constraints; ask only where the answer changes compatibility or selection.
Compare the existing composition, a prebuilt bundle and a provider where creation actually varies.

## When it is the answer

```text
There are 2+ product types that must agree with each other
        AND creation or selection needs a coherent family boundary
                → consider Abstract Factory or a prebuilt coherent family.

The family is selected once per deployment (profile, environment)
                → existing composition root; in Spring, one @Configuration per family.
                  Verify coherent wiring; profiles and qualifiers do not prove compatibility.

The family is selected per request / tenant / document / region
                → select a coherent provider or prebuilt family by key.
                  DI may supply that registry; use factory methods when creation varies.

Third-party code must contribute a whole family
                → Abstract Factory as the SPI shape (ServiceLoader
                  provider returning the family, not N providers).
```

## When it is not

- **One product type.** A constructor, named factory or `Supplier` may suffice
  (`java-object-construction`). GoF Factory Method applies when an inherited algorithm delegates
  creation to a subclass hook; not every creation method is that pattern.
- **The products are unrelated** — `createRepository`, `createHttpClient`, `createClock`. This
  is a service locator with a factory's name, and it re-couples every caller to one type that
  knows everything (`gof-pattern-antipatterns`).
- **The family differs only in constants.** Rates, endpoints, limits and timeouts are data. A
  class per value is the commonest false Abstract Factory; use configuration instead.
- **Only one family exists, and the second is speculative.** This weakens the case, but does not
  decide it: an interface can still be justified as a module or plugin boundary, an ownership
  seam, or a stable port. Record that reason; otherwise defer the abstraction until a second
  family reveals the real common contract.
- **Testing was the only motivation.** First prefer substituting collaborators at an existing
  boundary (plain injection, `@MockitoBean` for singleton beans in Spring Framework 6.2+, or a test
  `@Configuration`). A production
  family abstraction can still be warranted when the coherent in-memory family is itself a
  useful contract, not merely a test hook.

## Modern Java expression

A record of factory functions can package a small family without additional implementation
classes. Its constructor and suppliers still need compatibility, null, freshness and ownership
contracts; final references do not make captured state or products thread-safe. A record of
already-created products is a family bundle, not a factory of fresh products.

The examples target Java 17 without preview features (records and sealed types); pattern switches
over sealed hierarchies require Java 21 to avoid preview. Inspect the project's actual release and
dependencies; the pattern also works with ordinary classes on older Java without upgrades.

```text
Classical                          Modern
─────────────────────────────────  ────────────────────────────────────
interface ReportFactory            record ReportFamily(
  Renderer newRenderer()             Supplier<Renderer> renderer,
  Paginator newPaginator()           Supplier<Paginator> paginator,
  StyleSheet newStyleSheet()         Supplier<StyleSheet> styles)

class PdfReportFactory  implements  static ReportFamily pdf()
class HtmlReportFactory implements  static ReportFamily html()

selection: if/else or a Map        Map<Format, ReportFamily>, or a
                                   sealed Format with exhaustive switch
```

Keep the interface when a product needs more than construction from the family — shared
configuration, a `supports()` predicate, a lifecycle to close — or when third parties implement
it, since an interface is a stabler SPI contract than a record's component list.

## Decision rules

```text
IF the products can be used in any combination without breaking
THEN there is no family. Inject each product independently.

IF the family is fixed at startup by profile or property
THEN prefer existing composition, with or without a container. A factory called once
     still needs assessment of its SPI, compatibility or lifecycle responsibility.

IF the family key arrives from a request, a tenant or a document
THEN select a compatible prebuilt family or provider where creation varies, with
     an explicit failure for an unsupported key — never a silent default family.

IF the key comes from outside the process
THEN validate it against the supported registry before selection. Never turn an
     untrusted class name into reflective loading; an extensible plugin key need not
     be a compile-time closed enum, but it still needs authorization and failure policy.

IF a newly required product has no compatible default
THEN providers must supply it before consumers rely on it. Assess source, binary and
     semantic compatibility; a valid default or separate capability can sometimes avoid
     changing every provider. Do not invent a default merely to keep old plugins loading.

IF the factory starts caching what it creates
THEN define sharing, eviction, closure and thread safety. A cache alone is neither Flyweight
     nor Singleton; select those patterns only if their separate intent fits.
```

## Cross-cutting checks

- **Concurrency.** Share stateless providers when their products permit it; confine session-owned
  families or define synchronization where state is needed. Select one stable family for the whole
  operation: separately reading a mutable `currentFamily` for each product can mix families even
  if each read is thread-safe. Supplier calls are not an atomic multi-resource acquisition.
- **Distribution.** The pattern is process-local. A "remote factory" that returns handles to
  objects living elsewhere is a Proxy problem with the failure semantics that implies
  (`gof-proxy`). Where families correspond to protocol or schema versions, the selection is
  capability negotiation and needs an explicit unsupported-version path.
- **Performance.** The pattern does not imply allocation: a family may return cached, pooled or
  newly constructed products. Dispatch may inline at stable call sites and may become
  megamorphic with many implementations. Neither effect is a design-level reason to adopt or
  reject the pattern; profile the actual construction and call sites
  (`jit-inlining-and-escape-analysis`).
- **Testing.** The legitimate testing benefit is a whole coherent in-memory family, which makes
  integration-style tests fast without mocks. The illegitimate one is a factory added so that a
  single collaborator can be stubbed — inject that collaborator instead.

## Review checklist

- [ ] There are two or more products, and a stated invariant binds them
- [ ] The actual compatibility enforcement boundary is explicit and tested
- [ ] The selection key is named and validated against the authorized supported registry
- [ ] An unknown key fails loudly rather than falling back to a default family
- [ ] Multiple families exist, or a concrete SPI/module boundary justifies the abstraction
- [ ] Mutable factory, supplier and product state has an explicit concurrency/lifetime contract
- [ ] The products differ in behaviour, not only in configuration values
- [ ] Provider/consumer evolution preserves the required contract or has an explicit migration

Report the family invariant, chosen consumer API and why it fits better than the relevant simpler
alternative, enforcement/ownership boundary and actual checks. Keep adequate construction or wiring;
unresolved lifecycle or compatibility evidence makes the recommendation conditional.

## References

- [Decision and alternatives](references/decision-and-alternatives.md) — the family-invariant
  test, Abstract Factory against dependency injection, `Map<Key, Supplier>`, `ServiceLoader` and
  configuration, and how it differs from Factory Method and Builder. Read before introducing or
  removing a factory interface.
- [Worked example](references/worked-example.md) — a report-export family selected per request,
  built first as a classical hierarchy and then as a prebuilt record bundle, with the tenant-scoped
  variant, the failure path for an unknown format, and what each version costs. Read when
  implementing.

Attribution

robsonkadesrobsonkades
View sourceMore from robsonkades →
SSkills DirectorySkills Directory

Ship a skill? Prove it's safe.

Free 120-pattern security scan, letter grade, and an embeddable README badge.

Submit a skill

Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.

Comments (0)

No comments yet. Be the first to comment!

SSkills DirectorySkills Directory

Ship a skill? Prove it's safe.

Free 120-pattern security scan, letter grade, and an embeddable README badge.

Submit a skill

Related Skills

Browser Extension Developer

Use this skill when developing or maintaining browser extension code in the `browser/` directory, including Chrome/Firefox/Edge compatibility, content scripts, background scripts, or i18n updates.

281612 votes

Seo Optimizer

SEO optimization with keyword analysis, readability assessment, technical validation, content quality. Use for search rankings, blog posts, content audits, or encountering keyword density, readability scores, meta tags, schema markup errors.

2132 votes

Google Official Seo Guide

Official Google SEO guide covering search optimization, best practices, Search Console, crawling, indexing, and improving website search visibility based on official Google documentation

1862 votes

Tanstack Start

Build a full-stack TanStack Start app on Cloudflare Workers from scratch — SSR, file-based routing, server functions, D1+Drizzle, better-auth, Tailwind v4+shadcn/ui. Use whenever the user mentions TanStack Start, asks to scaffold a full-stack Cloudflare app with SSR, wants an SSR dashboard, or asks for a React 19 + Cloudflare Workers app with file-based routing and server functions — even if they don't name TanStack Start specifically. No template repo — Claude generates every file fresh per ...

9881 votes

Pentest

PTES-aligned adversarial security audit for backend, frontend, and mobile applications. Produces a CVSS-scored Hacker Report with verified PoCs and phased remediation.

5491 votes
View all in development →