A curated collection of object-oriented design patterns and concurrency constructs, each implemented in Java, Python, TypeScript and JavaScript, intended as teaching material. Every pattern has one academic write-up that is language-neutral, one idiomatic implementation per language reduced to the smallest set of classes that still shows the structure, tests, and a recorded output that continuous integration verifies is identical across the four languages.
This is the multi-language iteration of java-patterns-and-constructs.
- Quickstart
- Catalogue
- Principles
- Repository layout
- How it fits together
- Adding a pattern
- Future work
- References
Requirements: JDK 25 through SDKMAN! (sdk env in the
repository root selects it), uv, Node 20.19+
with pnpm (corepack enable).
git clone <this repository>
cd design-patterns-multi-language
sdk env
make setup # installs every toolchain's dependencies
make test # every language's tests and coverage gates
make run P=strategy # one pattern in all four languages, side by side
make run P=strategy L=python
make run-all L=python # every pattern in one language, in catalogue order
make list L=javaEach language can also be used on its own; see the README in java/,
python/, typescript/ and javascript/.
Patterns follow the classification of Gamma, Helm, Johnson and Vlissides [1],
plus a category for concurrency constructs. Each row links to the academic
write-up, which links to the implementation in every language. The table is
generated from catalog.yaml; do not edit it by hand.
| Pattern | Intent | Java | Python | TypeScript | JavaScript | |
|---|---|---|---|---|---|---|
| 🌰 | Abstract Factory | Provide an interface for creating families of related objects without naming their concrete classes. | done | done | done | done |
| 👷 | Builder | Separate the construction of a complex object from its representation so the same process can create different representations. | done | done | done | done |
| 🏭 | Factory Method | Define an interface for creating an object, but let subclasses decide which class to instantiate. | done | done | done | done |
| 🏗️ | Simple Factory | Centralise the creation of related products behind a single method that selects the concrete class. | done | done | done | done |
| 🔂 | Monostate | Share all state among every instance of a class while leaving instantiation unconstrained. | done | done | done | done |
| 🃏 | Prototype | Specify the kinds of objects to create using a prototypical instance, and create new objects by copying it. | done | done | done | done |
| 💍 | Singleton | Ensure a class has exactly one instance and provide a global point of access to it. | done | done | done | done |
| ♻️ | Object Pool | Reuse a bounded set of expensive-to-create objects by lending them out and taking them back instead of creating and discarding them. | done | done | done | done |
| Pattern | Intent | Java | Python | TypeScript | JavaScript | |
|---|---|---|---|---|---|---|
| 🔌 | Adapter | Convert the interface of a class into another interface clients expect. | done | done | done | done |
| 🌉 | Bridge | Decouple an abstraction from its implementation so the two can vary independently. | done | done | done | done |
| 🌿 | Composite | Compose objects into tree structures and let clients treat individual objects and compositions uniformly. | done | done | done | done |
| 🍧 | Decorator | Attach additional responsibilities to an object dynamically. | done | done | done | done |
| 🎁 | Façade | Provide a unified, higher-level interface to a set of interfaces in a subsystem. | done | done | done | done |
| 🍃 | Flyweight | Use sharing to support large numbers of fine-grained objects efficiently. | done | done | done | done |
| ☔ | Protection Proxy | Control access to an object by checking the caller's rights before forwarding a request. | done | done | done | done |
| 🍬 | Virtual Proxy | Defer the creation of an expensive object until it is actually needed. | done | done | done | done |
| Pattern | Intent | Java | Python | TypeScript | JavaScript | |
|---|---|---|---|---|---|---|
| 🐝 | Chain of Responsibility | Pass a request along a chain of handlers until one of them handles it. | done | done | done | done |
| 👫 | Command | Encapsulate a request as an object, allowing requests to be queued, logged and undone. | done | done | done | done |
| 🎶 | Interpreter | Given a language, define a representation for its grammar along with an interpreter that uses it. | done | done | done | done |
| 🍫 | Iterator | Provide sequential access to the elements of an aggregate without exposing its underlying representation. | done | done | done | done |
| 💐 | Mediator | Define an object that encapsulates how a set of objects interact, keeping them from referring to each other explicitly. | done | done | done | done |
| 💾 | Memento | Capture and externalise an object's internal state so it can be restored later, without violating encapsulation. | done | done | done | done |
| 👓 | Observer | Define a one-to-many dependency so that dependents are notified when a subject changes state. | done | done | done | done |
| 🐉 | State | Allow an object to alter its behaviour when its internal state changes; the object appears to change class. | done | done | done | done |
| 💡 | Strategy | Define a family of interchangeable algorithms and let the client choose one at run time. | done | done | done | done |
| 📝 | Template Method | Define the skeleton of an algorithm and defer some steps to subclasses. | done | done | done | done |
| 🏃 | Visitor | Represent an operation to be performed on the elements of an object structure without changing their classes. | done | done | done | done |
| 🫥 | Null Object | Provide a do-nothing collaborator with the expected interface so clients never test for null. | done | done | pending | pending |
| Construct | Problem | Java | Python | TypeScript | JavaScript | |
|---|---|---|---|---|---|---|
| 🔄 | Producer/Consumer | Coordinate threads that generate data with threads that process it through a bounded, thread-safe buffer. | done | done | done | done |
| 🚦 | Monitor | Bundle shared state with the lock and condition variables that guard it, so callers never synchronise by hand. | pending | pending | pending | pending |
| 📖 | Read/Write Lock | Let many readers share access to a resource while a writer gets it exclusively. | pending | pending | pending | pending |
| 🔮 | Future/Promise | Represent a result that will be available later, so callers compose and wait on it instead of blocking at once. | pending | pending | pending | pending |
| 🧵 | Thread Pool | Run submitted tasks on a fixed set of worker threads instead of creating a thread per task. | pending | pending | pending | pending |
| ⏸️ | Guarded Suspension | Suspend a call until its precondition holds, then run it. | pending | pending | pending | pending |
| Pattern | Intent | Java | Python | TypeScript | JavaScript | |
|---|---|---|---|---|---|---|
| 💎 | Value Object | A small immutable object whose equality rests on its value, not its identity. | pending | pending | pending | pending |
| 💰 | Money | Represent a monetary amount with its currency and exact arithmetic, including allocation that loses no cents. | pending | pending | pending | pending |
| 📦 | Data Transfer Object | Carry data between layers or processes in one object to reduce the number of calls. | pending | pending | pending | pending |
| 📇 | Registry | A well-known object through which other objects find common objects and services. | pending | pending | pending | pending |
| 🔌 | Plugin | Link classes during configuration rather than compilation. | pending | pending | pending | pending |
| 🎭 | Service Stub | Replace a problematic external service with a stand-in during development and testing. | pending | pending | pending | pending |
| 📜 | Transaction Script | Organise business logic as one procedure per request. | pending | pending | pending | pending |
| 🧠 | Domain Model | An object model of the domain that incorporates both behaviour and data. | pending | pending | pending | pending |
| 🛎️ | Service Layer | Define an application's boundary with a layer of services that coordinates the domain and exposes the available operations. | pending | pending | pending | pending |
| 🗂️ | Active Record | An object that wraps a row, encapsulates its data access and adds domain logic. | pending | pending | pending | pending |
| 🗺️ | Data Mapper | A layer of mappers that moves data between objects and a store while keeping the two independent. | pending | pending | pending | pending |
| 🪪 | Identity Map | Load each object once by keeping every loaded object in a map keyed by identity. | pending | pending | pending | pending |
| 📝 | Unit of Work | Track the objects affected by a business transaction and commit their changes as one. | pending | pending | pending | pending |
| 🏛️ | Repository | Mediate between the domain and the data mapping layer with a collection-like interface. | pending | pending | pending | pending |
| 🔒 | Optimistic Offline Lock | Detect conflicts between concurrent business transactions with a version check at commit. | pending | pending | pending | pending |
| 🖼️ | Model-View-Controller | Split user-interface interaction into model, view and controller. | pending | pending | pending | pending |
The patterns are not ends in themselves: each exists to honour one or more
design principles, such as encapsulate what varies or the open-closed
principle. docs/principles.md states those principles
with their sources, and every pattern document names, right after its intent,
the principles it relies on.
catalog.yaml single source of truth: patterns, languages, implementation paths
docs/ pattern-first academic documentation, conventions, references
java/ Maven project (JDK 25) one package per pattern
python/ uv project one package per pattern
typescript/ strict TypeScript, tsx, vitest one folder per pattern
javascript/ plain ESM Node, node:test one folder per pattern
tools/runner/ orchestrator CLI (TypeScript): validate, run, snapshot, check
snapshots/ recorded output per pattern and language, verified by CI
specs/ Spec Kit feature specifications, one per pattern
Makefile thin façade over everything above
PLAN.md architecture, decisions and phases
- The catalog lists every pattern, its documentation and where each language implements it. Nothing in one language knows about another.
- The contract. In every language, a pattern exposes an Example with an
idand arun(out)operation that writes only through an Output sink. Each language ships a small CLI withlist,run <id>andrun --all. - The orchestrator reads the catalog and drives the four CLIs, so
make run P=strategyshows the four outputs side by side, andmake checkproves they still match the recorded snapshots and each other. - The documentation is pattern-first and language-neutral, with a Mermaid
diagram of the participants only and a table mapping each role to the class
or function in each language. See
docs/conventions.md.
Development follows GitHub Spec Kit:
one specification per pattern, created from
.specify/templates/pattern-spec-template.md, planned, broken into tasks and
implemented on its own branch. The definition of done is in
PLAN.md.
In short: the academic doc with a participants-only diagram, an idiomatic
implementation with tests in each language, line and branch coverage above
90 %, a recorded snapshot per language, and make validate and make check
green.
Two catalogues were reviewed and deliberately left out of this repository: generative AI patterns and API design patterns. Each document records the candidate patterns, why they do not fit the contract here (no network, no secrets, byte-exact output in every language) and how a separate project could build them.
The shared bibliography is in docs/references.md.
Pattern documents cite it by number.