Module Quiz
Complete this quiz after finishing all concept and practice pages.
Current Module Questions
Question 1: Factory Method vs Abstract Factory
What is the single most important structural difference between Factory Method and Abstract Factory?
Answer: Factory Method uses inheritance -- a subclass overrides one method to pick a single concrete product. Abstract Factory uses composition -- a client holds a factory object that exposes multiple related creation methods, guaranteeing that all returned products belong to the same family.
Question 2: Builder Invariants
Why should a Builder validate invariants inside build() rather than inside each setter?
Answer: Because some invariants only make sense once all fields are set (for example, "if method is GET, body must be null"). Validating per-setter also forces callers into a specific ordering, which defeats the point of a fluent Builder.
Question 3: Adapter vs Facade
You are wrapping a third-party Stripe SDK and exposing a PaymentGateway with one method, charge(amount, token). Is this an Adapter or a Facade? Justify in one sentence.
Answer: It is an Adapter, because the SDK and the target interface have the same conceptual level (payment operations) and the wrapper is reshaping one interface into another for compatibility. A Facade would simplify many classes of a subsystem behind a smaller surface.
Question 4: Decorator vs Proxy -- Scenario
You add a class CachingUserRepo that implements the same interface as UserRepo and, on each call, either returns a cached value or delegates and caches. Is this Decorator or Proxy? Justify by intent.
Answer: It is most naturally a Proxy, specifically a caching/smart-reference proxy: the wrapper's intent is to control access to the subject (avoid re-fetching), not to add new behavior the caller asked for. Structurally identical to a Decorator; the intent ("control access" vs "add behavior") is what classifies it.
Question 5: Composite Uniform Treatment
Why does the Composite pattern require that Leaf and Composite share the same interface?
Answer: Because the whole point of Composite is that clients treat individuals and groups uniformly. If clients must branch on "leaf vs composite," the pattern's main win -- removing that conditional from every operation -- is lost.
Question 6: Composite Safety vs Transparency
What is the safety-versus-transparency trade-off in Composite, and which side does Head First favor?
Answer: Transparency puts child-management methods (add, remove) on the shared Component interface so clients truly cannot tell leaves from composites, at the cost of leaves having to reject child operations at runtime. Safety keeps those methods only on Composite, forcing clients to distinguish at compile time. Head First favors transparency for clients but acknowledges the loss of compile-time safety; real codebases often pick safety.
Question 7: Pick the Right Pattern -- Subsystem Simplification
A team works with a graphics library that exposes 40 public classes. 90% of internal callers use the same five methods across five of those classes. Which pattern applies and why?
Answer: Facade. The problem is too many public surfaces for the common case, not interface incompatibility. Facade covers the 80% workflow in one object while leaving the full subsystem reachable.
Question 8: Pick the Right Pattern -- Cross-cutting Behavior
A service makes HTTP calls. The team wants to add retry, structured logging, and metrics without touching the existing service class. Which pattern applies and why?
Answer: Decorator. Each cross-cutting concern becomes its own wrapper class implementing the same HTTP interface. The service stays unchanged; the decorators compose at the composition root. Proxy would be wrong in intent because the wrappers are adding behavior, not controlling access.
Question 9: Pick the Right Pattern -- Construction Complexity
A value type has 12 fields, several optional, some mutually exclusive (e.g., body only makes sense for non-GET requests). Which pattern applies and why?
Answer: Builder. It replaces a telescoping constructor with a readable, step-by-step recipe and centralizes invariant checks in build() where all fields are finally known.
Question 10: Singleton Justification
Why is "we only ever need one of these" not, on its own, a sufficient reason to make something a Singleton?
Answer: "One at a time" is a scoping concern the composition root already solves by constructing the object once and injecting it. Singleton bakes "exactly one" into the class, hides the dependency, and makes testing harder. Singleton is justified only when exactly-oneness is a genuine invariant of the process, not a convenience.
Question 11: DI vs Service Locator
What is the difference between dependency injection and a service locator, and why is DI usually preferred?
Answer: DI makes dependencies explicit at the constructor; a service locator hides them behind runtime lookups. With DI, a class's dependencies cannot be missed at compile time or review time; with a locator, any method can secretly pull any collaborator, which defeats the testability and discoverability gains DI is supposed to provide.
Question 12: Composition Root
Where should new statements for infrastructure collaborators (HTTP clients, DB clients, file systems) live, and why?
Answer: In the composition root -- a single startup function close to the application's entry point. Constraining new to that place means the rest of the code depends only on interfaces, environment configuration has one boundary, and test wirings can replace real infrastructure without touching domain code.
Question 13: Cargo-Cult Diagnosis
You see UserServiceFactoryImpl implements UserServiceFactory which produces UserServiceImpl as the only implementation of UserService, in one place in the codebase. What are you looking at and what refactor applies?
Answer: A cargo-culted factory plus an unused interface. Refactor: inline the factory, delete the interface, construct UserService directly at the composition root. The pattern is absorbing no variation.
Question 14: Simpler Alternatives
Give one example of a classical OO pattern that typically collapses to a function in languages with first-class functions, and describe the collapse.
Answer: Strategy collapses to passing a function. An interface with one method whose only implementations are single-method classes becomes a function type. The class-based form earns its cost only when multiple related methods, naming, or serialization matter.
Question 15: Pick the Right Pattern -- Orthogonal Variation
A rendering library needs to support two shape kinds (Circle, Square) and two backends (Raster, Vector). How do you avoid a combinatorial class explosion, and what pattern names the solution?
Answer: Bridge. Split the hierarchy into an abstraction (Shape: Circle, Square) and an implementation (Renderer: Raster, Vector). The abstraction holds a Renderer and delegates the "how" to it. New shapes or new renderers now grow additively instead of multiplicatively.
Interleaved Review Questions
Prior Module Question 1 (from S3 M3: Behavioral Patterns)
How does Strategy differ from Factory Method in terms of what varies?
Answer: Strategy varies behavior (the algorithm used at runtime). Factory Method varies which concrete object is produced at construction time. They often appear together: a factory picks a strategy.
Prior Module Question 2 (from S3 M3: Behavioral Patterns)
Why is Command often a useful collaborator for Decorator and Proxy?
Answer: Command encapsulates an operation as an object. A Decorator or Proxy can wrap a Command just like any other object -- logging, retrying, auditing the invocation -- without knowing what the command does. This is the pattern behind many middleware chains.
Prior Module Question 3 (from S3 M2: Refactoring)
What refactoring move removes a cargo-culted interface with a single implementation?
Answer: Inline Interface (effectively "Inline Class" applied to the interface), followed by Rename if needed. The single implementation becomes the concrete type everyone uses.
Prior Module Question 4 (from S3 M1: OOD Foundations)
How does dependency injection relate to coupling and cohesion?
Answer: DI reduces efferent coupling from a class to specific implementations (it depends only on interfaces) and tends to improve cohesion by pushing construction and configuration out of the class into the composition root.
Prior Module Question 5 (from S2: Data Structures)
Why is a tree-based data structure a natural fit for Composite?
Answer: Trees are recursive: a node either is a leaf or is a collection of other nodes. Composite makes the recursion explicit in the type system so operations on the whole tree can be written once, against the shared interface, without branching.
Self-Assessment and Remediation
Mastery Level (90-100% correct):
- Ready to advance. Move into Module 5 (Applied Design & Code Review).
Proficient Level (75-89% correct):
- Review only the missed concept pages. Redo one kata per missed pattern.
Developing Level (60-74% correct):
- Rework the practice pages, especially the Composition and DI Clinic and the Interface Bridging Workshop. Pay extra attention to intent questions (Adapter vs Facade, Decorator vs Proxy).
Insufficient Level (<60% correct):
- Return to the concept sequence. Rebuild the habit of naming the force before naming the pattern. Consider revisiting Module 1 (cohesion and coupling) and Module 3 (Strategy, Command) -- many of this module's misunderstandings trace back there.