skip to content

Creator

Decide which class should construct another: usually the one that contains, aggregates, records or closely uses it. You will learn when this simple heuristic is enough and when creation is complicated enough to deserve a factory.

part ofSoftware design & architectureoverview, primer and where to startread it →
on this pageshow

questions

6

What does the GRASP "Creator" principle say about deciding which class should be responsible for creating instances of another class?

level: juniorimportance: must knowfreq 55%

answer

  1. aggregates / contains / records / closely uses / has init data
  2. creation adds no NEW coupling edge
  3. Low Coupling applied to instantiation
  4. initializing data = strongest tie-break
  5. complex construction → Factory / Pure Fabrication

basics

~20 s

Creator says: give the job of making a new object to a class that already aggregates, contains, records, closely uses, or holds the data needed to build it. That class already knows about it, so creating it adds no new coupling.

solid answer

~50 s

GRASP (General Responsibility Assignment Software Patterns) is a set of nine heuristics for deciding which class gets which responsibility. "Creator" answers one specific question: who should instantiate class A? Assign creation of A to class B if B aggregates A objects, contains A objects, records A instances, closely uses A, or has the initializing data that A's constructor requires. The motivation is coupling: B already has to know about A for one of those reasons, so making B the creator introduces no *new* dependency edge in the design. If several classes qualify, prefer the one that aggregates or contains A (it owns A's lifetime), and, where that is ambiguous, the one holding the initializing data. Creator is a default, not a law — when construction is complex, conditional, or must vary by configuration, delegate to a Factory Method, Abstract Factory, Builder, or a Pure Fabrication factory class instead.

code

pseudocode · 15 lines
pseudocode
// Creator: Order aggregates + contains OrderLine, and holds the collection
class Order {
  private lines = []

  addLine(product, quantity) {          // Order is the Creator
    line = new OrderLine(product, quantity)
    lines.add(line)
    recalculateTotal()                   // invariant stays enforceable
    return line
  }
}

// Anti-pattern: an outside class builds the part and pokes it in
line = new OrderLine(product, qty)       // controller now depends on OrderLine
order.getLines().add(line)               // internals leaked, total not updated

go deeper

for a junior

State the rule and one criterion with an example: Order creates OrderLine because it contains them. Mention that it keeps coupling low.

for a middle

List all five criteria, explain the coupling rationale, and name the tie-break (aggregation/ownership, then initializing data). Give a concrete before/after.

for a senior

Frame Creator as Low Coupling applied to instantiation, relate it to Information Expert and Pure Fabrication, and state explicitly when to override it with a Factory/Builder or DI.

for a principal

Discuss creation as lifecycle ownership: aggregate roots, invariant enforcement at the creation boundary, reconstitution vs creation in ORMs, and where the composition root ends and domain creation begins.

## What GRASP is **GRASP** stands for *General Responsibility Assignment Software Patterns* (Craig Larman, *Applying UML and Patterns*). It is a set of nine naming-and-reasoning heuristics — Information Expert, Creator, Controller, Low Coupling, High Cohesion, Polymorphism, Pure Fabrication, Indirection, Protected Variations — for the most basic activity in object design: **deciding which class should hold which responsibility**. They are not code patterns like Singleton or Observer; they are decision rules you apply *before* you reach for such patterns. A **responsibility** here means an obligation of an object: either *doing* something (compute, create, coordinate) or *knowing* something (its own data, related objects, derivable values). ## The Creator heuristic, precisely > **Problem:** Who should be responsible for creating a new instance of some class `A`? > > **Solution:** Assign that responsibility to a class `B` if **one or more** of the following is true: > 1. `B` **aggregates** `A` objects (whole-part with ownership), > 2. `B` **contains** `A` objects (holds them in a collection/field), > 3. `B` **records** instances of `A` (keeps a registry/log of them), > 4. `B` **closely uses** `A` objects, > 5. `B` **has the initializing data** that will be passed to `A` at construction (`B` is an *Information Expert* with respect to `A`'s construction). > > Rule 5 is the strongest tie-breaker when the others conflict; rules 1–2 (ownership of lifetime) are usually preferred when several classes are otherwise equal. ### Why this rule and not something else Every `new A(...)` in class `B` creates a **compile-time dependency** from `B` to `A`. Design quality is largely about keeping the dependency graph small and acyclic. Creator's insight is: *if `B` already depends on `A` anyway* (because it stores it, owns it, or uses it), then adding "and `B` builds it" costs **zero new edges**. Handing creation to some unrelated class `C` would add a brand-new edge `C → A` for no benefit. So Creator is really **Low Coupling applied to instantiation**. A second benefit is **lifecycle clarity**: the object that creates a part is usually the object that can decide when the part dies, is replaced, or must be kept consistent. Ownership and creation travelling together makes invariants enforceable. ## Concrete illustration (language-neutral) Domain: an `Order` holds many `OrderLine`s; each line references a `Product` and a quantity. - Who creates `OrderLine`? **`Order`** — it aggregates and contains lines, and it holds the collection the new line must join. So `Order.addLine(product, qty)` internally constructs the line. - If a UI or controller did `new OrderLine(...)` and then `order.lines.add(line)`, the controller gains a dependency on `OrderLine`, `Order` must expose its internal collection, and `Order` can no longer guarantee invariants such as "no duplicate product lines" or "total must be recomputed". ## The five criteria, one at a time | Criterion | Meaning | Example | |---|---|---| | aggregates | whole–part with ownership; part dies with whole | `Order` → `OrderLine`, `Document` → `Paragraph` | | contains | holds in a field/collection (weaker than aggregation) | `Playlist` → `TrackEntry` | | records | keeps a log/registry of instances it did not necessarily own | `AuditLog` → `AuditEntry`, `Board` → `Move` | | closely uses | calls it heavily, works with it intimately | `HttpClient` → `Request` | | has initializing data | already knows every value the constructor needs | `Payment` knows amount + currency → creates `Money` | ## Trade-offs and when Creator is the wrong answer Creator is a **default heuristic**, applied when creation is simple. Deviate when: 1. **Creation is complex or conditional.** Choosing among subclasses, reading configuration, applying caching/pooling, or long multi-step assembly. Then use a **Factory Method**, **Abstract Factory**, **Builder**, or a dedicated factory class (**Pure Fabrication** — a made-up class with no domain counterpart, invented to preserve cohesion). 2. **Creation would drag heavy dependencies in.** If constructing `A` needs a database connection, a clock, or a remote service, letting the domain `B` create it pollutes `B` with infrastructure. Inject an abstraction instead. 3. **You want to vary the implementation** (test doubles, plugins, feature-flagged variants). Hard-coded `new` is not substitutable, so hand construction to a factory or a dependency-injection **composition root** (the single place near the program's entry point where the object graph is wired). 4. **The object is long-lived and shared** (services, repositories, connection pools). Creator is about *domain/entity/value* objects; wiring of long-lived collaborators is a container/composition-root concern. ## Relation to the other GRASP heuristics - **Information Expert** ("assign a responsibility to the class that has the information needed to fulfil it") is the parent idea; criterion 5 is literally Information Expert applied to construction. - **Low Coupling / High Cohesion** are the evaluative principles Creator optimises for; if following Creator visibly *worsens* them (e.g. the domain class becomes a giant assembler), the evaluative principles win. - **Pure Fabrication** is the standard escape hatch: invent `OrderFactory` when neither `Order` nor anything else in the domain should own the messy construction. ## Common edge cases - **Deserialization / ORM materialisation.** Frameworks reconstruct objects by reflection, bypassing your Creator. That is *reconstitution*, not *creation*; keep a separate path (e.g. a package-private constructor) and don't let it weaken the invariants enforced on the real creation path. - **Circularity.** If `A` creates `B` and `B` creates `A`, you have a cycle; usually a third class or a parameter object should own creation. - **Immutability.** With immutable objects, "modifying" means creating a replacement; the Creator is then also the class that must rebuild and re-store it. - **Static factory methods on the created class itself** (`Money.ofMinorUnits(...)`) do not violate Creator; they are a naming/validation convenience, and the *caller* is still chosen by Creator.

  • If two different classes both satisfy Creator criteria for the same class, how do you choose?
    Prefer the class that aggregates or contains the instance, because it owns the object's lifetime and can enforce invariants. If that is still ambiguous, pick the class that already holds the initializing data — that is the Information Expert criterion and it avoids passing data around just to construct.
  • Does using a dependency-injection container mean Creator no longer applies?
    No. Containers wire long-lived collaborators (services, repositories) at the composition root. Creator governs short-lived domain objects — entities, value objects, DTOs, events — which are created per operation from runtime data and should not come from a container.
  • Is a static factory method like Money.of(amount, currency) a violation of Creator?
    No. It changes only how construction is expressed and validated on the created type; Creator still decides which collaborating class should call it.

A restaurant kitchen makes the plate of food, not the customer — the kitchen already owns the ingredients, the recipe and the plates. Asking the customer to assemble the dish would force them to learn everything the kitchen already knows.

context

open as a page

The GRASP "Creator" heuristic lists several criteria for choosing a creating class (aggregates, contains, records, closely uses, has initializing data). What does each mean, and how do you decide when two candidate classes both qualify?

level: middleimportance: must knowfreq 45%

basics

~20 s

Aggregates/contains means it holds the object; records means it logs instances; closely uses means it works with it heavily; has initializing data means it already knows the constructor arguments. If several fit, prefer the owner (aggregator/container); otherwise the one with the data.

open as a page

In an order-entry system a controller receives "add product P with quantity 3 to order O". Applying the GRASP "Creator" heuristic, which class should construct the new order-line object, and what concretely goes wrong if the controller constructs it instead?

level: middleimportance: should knowfreq 40%

basics

~20 s

The Order should build the line, because it contains and owns its lines and holds the collection they join. If the controller builds it, the controller must know the line type, the order must expose its internal list, and totals or duplicate rules can silently break.

open as a page

How does the GRASP "Creator" heuristic coexist with dependency injection and a composition root? Which objects should still be created by the class that owns them, and which should be injected?

level: seniorimportance: should knowfreq 33%

basics

~20 s

Inject long-lived collaborators — services, repositories, gateways, clients — wired once at startup. Keep creating short-lived, data-carrying objects (entities, value objects, events, DTOs) inside the class that owns or has their data, as Creator says. When both are needed, inject a factory.

open as a page

When should you deviate from the GRASP "Creator" heuristic and introduce a dedicated factory (Factory Method, Abstract Factory, Builder, or a Pure Fabrication factory class) instead of letting the aggregating/using class call the constructor directly?

level: seniorimportance: should knowfreq 42%

basics

~20 s

Deviate when construction is complicated or must vary: choosing among subclasses, reading configuration, caching or pooling, many optional parameters, or needing infrastructure like a clock or database. Then a factory keeps the owning class simple and lets the built type change.

open as a page

At architectural scale, how does the GRASP "Creator" heuristic extend into lifecycle ownership — who may create objects that cross module or bounded-context boundaries, and how does object reconstitution by persistence frameworks interact with it?

level: principalimportance: nice to knowfreq 18%

basics

~20 s

Each module should own creation of its own types: outsiders send a request or data, and the owning module builds the object and checks the rules. Loading objects from a database is rebuilding an already-valid object, not creating a new one, so it may use a separate hidden path.

open as a page