RepoPilotOpen in app →

iluwatar/java-design-patterns

Design patterns implemented in Java

WAIT

Mixed signals — read the receipts

  • Last commit 1d ago
  • 5 active contributors
  • Other licensed
  • CI configured
  • Tests present
  • Small team — 5 top contributors
  • Concentrated ownership — top contributor handles 70% of commits
  • Non-standard license (Other) — review terms

Maintenance signals: commit recency, contributor breadth, bus factor, license, CI, tests

Embed this verdict

[![RepoPilot: WAIT](https://repopilot.app/api/badge/iluwatar/java-design-patterns)](https://repopilot.app/r/iluwatar/java-design-patterns)

Paste into your README — the badge live-updates from the latest cached analysis.

Onboarding doc

Onboarding: iluwatar/java-design-patterns

Generated by RepoPilot · 2026-05-05 · Source

Verdict

WAIT — Mixed signals — read the receipts

  • Last commit 1d ago
  • 5 active contributors
  • Other licensed
  • CI configured
  • Tests present
  • ⚠ Small team — 5 top contributors
  • ⚠ Concentrated ownership — top contributor handles 70% of commits
  • ⚠ Non-standard license (Other) — review terms

<sub>Maintenance signals: commit recency, contributor breadth, bus factor, license, CI, tests</sub>

TL;DR

A comprehensive Java monorepo implementing over 100 Gang-of-Four and enterprise design patterns (Abstract Factory, Abstract Document, Builder, etc.), each in its own Maven submodule with a runnable App.java, unit tests, and UML diagrams. It solves the problem of having no single authoritative, tested, Java-idiomatic reference for design patterns by providing working code with explanations rather than pseudocode. Flat monorepo: each pattern (e.g., abstract-document/, abstract-factory/) is an independent Maven submodule with its own pom.xml, src/main/java/.../App.java entry point, src/test/java/ tests, and etc/ directory containing PNG and PlantUML (.puml) diagrams. The root pom.xml at version 1.26.0-SNAPSHOT aggregates all submodules.

Who it's for

Java developers (junior to senior) who want to study or reference concrete, runnable implementations of design patterns. Also used by interviewers and educators who need vetted code examples, and open-source contributors looking to add new pattern implementations in Java.

Maturity & risk

Extremely mature: 392 contributors listed in .all-contributorsrc, a full GitHub Actions CI pipeline (maven-ci.yml, maven-pr-builder.yml, presubmit.yml), SonarCloud coverage badges, and MIT license since 2014. The project is production-quality as a learning/reference resource and actively maintained.

Very low risk for its intended use as a reference library — it is not a runtime dependency you ship. The main risk is that some patterns may use older Java idioms (pre-records, pre-sealed classes) as the codebase is large and not all modules are updated simultaneously. Dependabot (.github/dependabot.yml) manages dependency freshness, and SLF4J/Logback are the only runtime deps per module.

Active areas of work

The repo is on version 1.26.0-SNAPSHOT indicating active pre-release development. Dependabot (.github/dependabot.yml) is continuously filing dependency update PRs. The stale.yml workflow actively closes abandoned PRs, suggesting a high volume of community contributions being triaged.

Get running

git clone https://github.com/iluwatar/java-design-patterns.git cd java-design-patterns ./mvnw install -DskipTests # build all modules cd abstract-document ../mvnw compile exec:java -Dexec.mainClass=com.iluwatar.abstractdocument.App

Daily commands: ./mvnw install # build and test everything ./mvnw install -DskipTests # build only cd abstract-document && ../mvnw exec:java -Dexec.mainClass=com.iluwatar.abstractdocument.App

Map of the codebase

  • README.md — Master index of all implemented design patterns with categorization, usage guidance, and links — the primary navigation document for the entire repo.
  • abstract-factory/src/main/java/com/iluwatar/abstractfactory/KingdomFactory.java — Canonical abstract factory interface that exemplifies the repo's pattern implementation convention every contributor must follow when adding new patterns.
  • abstract-document/src/main/java/com/iluwatar/abstractdocument/AbstractDocument.java — Core abstract base class demonstrating how the repo structures reusable pattern skeletons with typed property maps and stream-based child access.
  • abstract-factory/src/main/java/com/iluwatar/abstractfactory/App.java — Standard App.java entry-point pattern used across all modules — every pattern module follows this convention for demonstrating usage via a main method.
  • CONTRIBUTING.MD — Defines the contribution standards, coding conventions, and the checklist every contributor must satisfy before submitting a new pattern or fix.
  • .github/workflows/maven-ci.yml — CI pipeline that runs on every push — defines how the multi-module Maven build is verified, making it essential for understanding build requirements.
  • AGENTS.md — Documents automated agent rules and constraints for this repo, critical for understanding how AI-assisted contributions are governed.

How to make changes

Add a New Design Pattern Module

  1. Create a new top-level directory (e.g. my-pattern/) with a pom.xml following the structure of an existing module like abstract-factory. (abstract-factory/pom.xml)
  2. Define the core pattern interface(s) in src/main/java/com/iluwatar/mypattern/, modeled after existing interfaces like KingdomFactory.java. (abstract-factory/src/main/java/com/iluwatar/abstractfactory/KingdomFactory.java)
  3. Implement at least two concrete implementations to demonstrate the pattern, following the Elf/Orc naming convention for clarity. (abstract-factory/src/main/java/com/iluwatar/abstractfactory/ElfKingdomFactory.java)
  4. Create an App.java entry point with a main method that narrates and demonstrates the pattern usage with log output. (abstract-factory/src/main/java/com/iluwatar/abstractfactory/App.java)
  5. Write JUnit tests covering the pattern's contract in src/test/java/com/iluwatar/mypattern/, referencing AbstractFactoryTest.java as a template. (abstract-factory/src/test/java/com/iluwatar/abstractfactory/AbstractFactoryTest.java)
  6. Add a README.md in the module root documenting intent, UML diagram, applicability, and real-world examples per the repo convention. (abstract-factory/README.md)

Add a New Product to an Existing Abstract Factory

  1. Define a new product interface (e.g. Wizard.java) in the pattern package, following the style of Army.java or King.java. (abstract-factory/src/main/java/com/iluwatar/abstractfactory/Army.java)
  2. Add the factory method for the new product to the KingdomFactory interface. (abstract-factory/src/main/java/com/iluwatar/abstractfactory/KingdomFactory.java)
  3. Implement the concrete product for each existing factory (ElfWizard, OrcWizard) and register them in ElfKingdomFactory and OrcKingdomFactory. (abstract-factory/src/main/java/com/iluwatar/abstractfactory/ElfKingdomFactory.java)
  4. Update App.java to demonstrate the new product creation and update AbstractFactoryTest.java to assert the new product type. (abstract-factory/src/test/java/com/iluwatar/abstractfactory/AbstractFactoryTest.java)

Add a New Typed Property Trait to Abstract Document

  1. Add a new key to the Property enum (e.g. COLOR) in the domain enums package. (abstract-document/src/main/java/com/iluwatar/abstractdocument/domain/enums/Property.java)
  2. Create a new mixin interface (e.g. HasColor.java) with a default accessor method using get(Property.COLOR), following HasPrice.java's pattern. (abstract-document/src/main/java/com/iluwatar/abstractdocument/domain/HasPrice.java)
  3. Have the relevant domain class (e.g. Car or Part) implement the new HasColor interface alongside existing traits. (abstract-document/src/main/java/com/iluwatar/abstractdocument/domain/Car.java)
  4. Add test assertions for the new property in DomainTest.java verifying the accessor returns expected values. (abstract-document/src/test/java/com/iluwatar/abstractdocument/DomainTest.java)

Add a New Concurrent Active Object Creature

  1. Create a new class (e.g. Elf.java) extending ActiveCreature in the activeobject package, following Orc.java's structure. (active-object/src/main/java/com/iluwatar/activeobject/Orc.java)
  2. Override the name() method and add any creature-specific async behaviors by submitting tasks to the inherited executor. (active-object/src/main/java/com/iluwatar/activeobject/ActiveCreature.java)
  3. Instantiate and exercise the new creature in App.java to demonstrate it running alongside other active creatures. (active-object/src)

Traps & gotchas

  1. The Maven wrapper (.mvn/wrapper/maven-wrapper.properties) pins a specific Maven version — do not use a system-installed Maven as it may differ. 2) Each submodule must be registered in the root pom.xml <modules> block or it will be silently ignored by the build. 3) The logback-classic dependency is declared in the parent POM's dependencyManagement, so adding it in a child pom.xml requires no version — specifying one will cause a warning/conflict. 4) PlantUML diagram in etc/ is required by the PR checklist in CONTRIBUTING.MD; missing it will block merge.

Concepts to learn

  • Abstract Document Pattern — The abstract-document/ submodule implements this lesser-known pattern for handling semi-structured data with type-safe trait interfaces (HasModel, HasPrice) — understanding it requires knowing why it differs from a plain Map.
  • PlantUML Class Diagrams — Every pattern has a .urm.puml file in its etc/ directory; contributors must generate and update these diagrams, so reading PlantUML syntax is a practical requirement.
  • Maven Multi-Module Build — The entire repo is structured as a Maven multi-module project where the root pom.xml aggregates 100+ submodules — understanding parent/child POM inheritance is essential for adding or modifying patterns.
  • Gang of Four (GoF) Design Patterns — The repo is organized around the 23 original GoF patterns plus modern enterprise patterns — knowing the original classification (Creational/Structural/Behavioral) helps navigate which submodule to look in.
  • SLF4J Facade Pattern — Every module uses SLF4J as the logging API with Logback as the runtime implementation — this is itself an example of the Facade pattern and a real-world Java logging convention contributors must follow.
  • Mixin / Trait Interface (Java default methods) — Interfaces like HasModel, HasPrice, and HasParts in the abstract-document pattern use Java default methods to compose behavior — this is the Java idiom for mixins and is used across multiple patterns in this repo.

Related repos

  • faif/python-patterns — The Python equivalent of this repo — same concept of catalogued design pattern implementations, useful for comparing language-idiomatic approaches.
  • kamranahmedse/design-patterns-for-humans — A prose-first explanation of the same GoF patterns that complements this code-first repo.
  • spring-projects/spring-framework — Spring uses many of the patterns implemented here (Template Method, Factory, Proxy, Decorator) in production — seeing them in Spring gives real-world context.
  • iluwatar/java-design-patterns — This is the canonical upstream; forks should track it for new pattern additions and dependency updates.
  • RefactoringGuru/design-patterns-java — A commercial alternative Java pattern catalogue — useful to cross-reference implementation choices against this repo.

PR ideas

To work on one of these in Claude Code or Cursor, paste: Implement the "<title>" PR idea from CLAUDE.md, working through the checklist as the task list.

Add missing unit tests for AbstractDocument property casting edge cases in AbstractDocumentTest.java

The existing AbstractDocumentTest.java likely covers the happy path for get/put operations, but the AbstractDocument class's generic get() method with stream-based child document construction (used in HasParts, HasType, etc.) is prone to ClassCastException and null-pointer edge cases that are not exercised. Adding tests for null property values, missing keys, and malformed child maps would prevent regressions and improve SonarCloud coverage metrics visible in the README badge.

  • [ ] Open abstract-document/src/test/java/com/iluwatar/abstractdocument/AbstractDocumentTest.java and audit which branches of AbstractDocument.java are not yet covered
  • [ ] Add a test case that calls get(Property.MODEL) on a document where the key is absent, asserting an empty Optional is returned
  • [ ] Add a test case that puts a null value for a property key and verifies the stream-based accessors in HasParts.java handle null map entries without throwing NullPointerException
  • [ ] Add a test case in DomainTest.java that constructs a Part with an incomplete property map (missing PRICE or TYPE) and asserts the Optional accessors return empty rather than throwing
  • [ ] Run mvn test -pl abstract-document and verify all new tests pass and coverage improves

Refactor ElfKingdomFactory and OrcKingdomFactory in abstract-factory to use a shared abstract base class, reducing duplication

ElfKingdomFactory.java and OrcKingdomFactory.java both implement KingdomFactory.java and almost certainly contain duplicated structural boilerplate (field declarations, constructor patterns, or logging). Introducing an AbstractKingdomFactory base class would demonstrate the Template Method pattern alongside Abstract Factory, making this module a richer teaching example — which is the core value proposition of the entire repo. This is a concrete refactoring opportunity visible directly from the file listing.

  • [ ] Open abstract-factory/src/main/java/com/iluwatar/abstractfactory/ElfKingdomFactory.java and OrcKingdomFactory.java and identify all duplicated method bodies or fields
  • [ ] Create a new file AbstractKingdomFactory.java in the same package that implements KingdomFactory.java and extracts shared logic (e.g., a getDescription() or logging method)
  • [ ] Make ElfKingdomFactory and OrcKingdomFactory extend AbstractKingdomFactory instead of directly implementing KingdomFactory
  • [ ] Update abstract-factory/README.md to document the new AbstractKingdomFactory and update the UML diagram at abstract-factory/etc/abstract-factory.urm.puml
  • [ ] Run mvn test -pl abstract-factory to confirm existing tests still pass, then open a PR

Add a GitHub Actions workflow for automated Checkstyle and SpotBugs reporting as a PR status check

The repo has maven-ci.yml and maven-pr-builder.yml under .github/workflows but no dedicated static-analysis workflow that surfaces Checkstyle or SpotBugs violations as inline PR annotations. The parent pom.xml almost certainly already declares these plugins (common in this project), but their output is buried in Maven logs. A dedicated workflow using the jwgmeligmeyling/checkstyle-github-action and jwgmeligmeyling/spotbugs-github-action actions would surface violations as GitHub code annotations directly on changed lines in PRs, which is a concrete quality gate improvement beyond what the existing workflows provide.

  • [ ] Verify the root pom.xml includes the maven-checkstyle-plugin and spotbugs-maven-plugin by inspecting the build/plugins section
  • [ ] Create .github/workflows/static-analysis.yml that triggers on pull_request events
  • [ ] Add a step running mvn checkstyle:checkstyle spotbugs:spotbugs -f pom.xml --no-transfer-progress to generate XML reports

Good first issues

  1. Add missing AppTest.java coverage for any pattern submodule that only has a domain test but no AppTest — e.g., verify abstract-document/AppTest.java actually exercises all App.java branches. 2) Several etc/*.puml diagrams may be out of sync with current code — pick one pattern, regenerate the PNG from the .puml using PlantUML CLI, and submit the updated abstract-document/etc/abstract-document.png. 3) Add a @DisplayName and @Tag annotation to existing JUnit 5 tests (e.g., DomainTest.java in abstract-document) to improve test reporting consistency across all submodules.

Top contributors

Recent commits

  • d24dd22 — feat: Add AGENTS.md (iluwatar)
  • 2d39fe7 — docs: add Olexandr88 as a contributor for doc (#3440) (allcontributors[bot])
  • b8f8199 — docs: Update README.md (#3298) (Olexandr88)
  • ce5154e — docs: add skamble2 as a contributor for code (#3437) (allcontributors[bot])
  • 265e3d0 — feat: Rate Limiting Pattern #2973 (#3291) (skamble2)
  • a3fcc63 — feat: Implement View Helper pattern (#3278) (e5LA)
  • dc3425d — docs: add letdtcode as a contributor for code (#3429) (allcontributors[bot])
  • 7c12643 — docs: add naman-sriv as a contributor for code (#3428) (allcontributors[bot])
  • 4caa0bf — docs: Persian translation: Abstract Factory (#3280) (maziyar-gerami)
  • f92e682 — feat: Implement DAO Factory pattern (#3282) (letdtcode)

Security observations

  • Medium · Outdated or Unversioned Dependencies — abstract-document/pom.xml. The pom.xml dependency file references dependencies like slf4j-api and logback-classic without explicit pinned versions (inheriting from parent BOM). If the parent BOM references outdated versions of logback-classic (prior to 1.2.12 / 1.3.8 / 1.4.8), the project may be vulnerable to CVE-2023-6378 (logback JNDI injection / serialization vulnerability) or older CVEs such as CVE-2021-42550. Similarly, if slf4j is older than 2.0.x, there may be indirect risks. Fix: Explicitly pin logback-classic to >= 1.4.14 and slf4j-api to >= 2.0.9. Run 'mvn dependency:tree' to audit transitive dependencies and integrate tools like OWASP Dependency-Check or Dependabot (which is already configured) to receive automated alerts.
  • Medium · Dependabot Configured but Remediation Not Enforced — .github/dependabot.yml. While .github/dependabot.yml is present and suggests automated dependency update PRs are configured, there is no evidence of branch protection rules or required status checks that enforce merging of security updates. This means vulnerable dependency PRs raised by Dependabot could remain open indefinitely without being acted upon. Fix: Enforce branch protection rules on the main branch requiring Dependabot security PRs to be merged within a defined SLA. Consider enabling Dependabot security alerts and auto-merge for patch-level security updates.
  • Low · Snapshot Version in Production Build — pom.xml (parent). The project version is declared as '1.26.0-SNAPSHOT' in the parent POM. SNAPSHOT versions are non-deterministic and mutable; Maven may resolve different artifact contents at different build times from snapshot repositories, introducing supply chain risk if snapshot repositories are not tightly controlled. Fix: Use release versions for all production or published artifacts. Restrict SNAPSHOT usage to development branches only and ensure snapshot repositories are hosted internally with access controls.
  • Low · Lack of SECURITY.md or Vulnerability Disclosure Policy — Repository root. The repository does not appear to include a SECURITY.md file defining a responsible disclosure or vulnerability reporting process. This is a recommended practice per GitHub and industry standards (e.g., OpenSSF), and its absence may delay coordinated disclosure of vulnerabilities found in the project. Fix: Add a SECURITY.md file to the repository root describing how to report vulnerabilities, the supported versions, and the expected response timeline. Reference GitHub's security advisory feature for private reporting.
  • Low · CI Workflow Permissions Not Explicitly Restricted — .github/workflows/maven-ci.yml, .github/workflows/maven-pr-builder.yml, .github/workflows/presubmit.yml. The GitHub Actions workflow files (maven-ci.yml, maven-pr-builder.yml, presubmit.yml) do not appear to explicitly set 'permissions' at the workflow or job level. Without explicit least-privilege permission declarations, workflows may inherit broader default permissions (e.g., write access to contents or packages), increasing blast radius if a workflow is compromised via a malicious dependency or PR. Fix: Add explicit 'permissions' blocks to each workflow and job, granting only the minimum required permissions (e.g., 'contents: read'). For PR builder workflows triggered by pull_request_target, be especially careful to avoid granting write permissions to untrusted code.
  • Low · Potential Unsafe Deserialization in AbstractDocument Pattern — abstract-document/src/main/java/com/iluwatar/abstractdocument/AbstractDocument.java. The AbstractDocument pattern stores arbitrary objects in a Map<String, Object> structure. If any serialization/deserialization mechanism (e.g., JSON, Java serialization) is applied to these documents with untrusted input in a real application context, it could lead to unsafe deserialization. While this is a demo/educational codebase, the pattern itself does not enforce type safety or input validation on stored values. Fix: If this pattern is adapted for production use, ensure strict type validation when retrieving values from the document map, avoid deserializing untrusted data into Object types, and consider using type-safe alternatives or schema validation.
  • Low · FUNDING — undefined. undefined Fix: undefined

LLM-derived; treat as a starting point, not a security audit.

Where to read next


Generated by RepoPilot. Verdict based on maintenance signals — see the live page for receipts. Re-run on a new commit to refresh.

WAIT · iluwatar/java-design-patterns — RepoPilot Verdict