Skip to main content

Pattern Integration Lab

Build one real feature that legitimately uses several patterns together. The goal is not "use three patterns." The goal is to put yourself in a situation where each pattern has a pressure, and practice seeing the pressure before naming the pattern.

Retrieval Prompts

Answer closed-book before starting:

  1. What pressure does Strategy absorb? What does Decorator absorb? What does Factory absorb?
  2. How do you tell whether a pattern is carrying its weight or is pattern salad?
  3. What are the four rules of simple design, in order?

The Target Feature

Build a PricingEngine for an imaginary online shop. Requirements:

  • Three credible pricing algorithms today (regular, seasonal, loyalty).
  • Every pricing call must be logged; some deployments also cache results for the same cart for 30 seconds.
  • Storefront configuration picks the base strategy; the caller should not know which storefront is which.
  • Tests cover: correctness of each strategy, logging happens exactly once per call, caching returns the cached value on a repeat call.

Your language is your choice. Python or TypeScript recommended for brevity.

Workflow

  1. Name the pressures. In your README, write a table with columns: pressure, smell or force it would produce without a pattern, proposed pattern, cost accepted.
  2. Write the simplest version first. Three strategies, one price() call, no decorators. Commit.
  3. Add the decorators. Logging decorator, then caching decorator. Commit each as a separate step.
  4. Introduce the factory. A PricingFactory that assembles strategy + decorators based on storefront config. Commit.
  5. Write the tests. Each algorithm, each decorator, and one end-to-end test through the factory.
  6. Write an ADR. "ADR 0001: Use Strategy + Decorator + Factory in the PricingEngine." Include alternatives considered (inheritance hierarchy, if/else chain).

Compare and Distinguish

  • Strategy vs. Template Method -- which is right here, and why?
  • Decorator vs. baking logging into each Strategy -- which is cheaper if you add a fourth strategy later?
  • Factory vs. direct construction -- what pressure justifies the factory in this specific feature?

Common Mistake Check

Identify the error in each:

  1. "I added a DiscountStrategy interface even though there is only one discount type today, because you might add more later."
  2. "Logging is hand-written in each of the three strategies; the code is identical, but it's faster to copy."
  3. "The factory does a switch on storefront inside PricingEngine.price() instead of in a dedicated class."
  4. "The caching decorator has its own copy of compute_total rather than delegating to the inner strategy."

Evidence Check

This lab is complete only if:

  • The README has the pressure table described above.
  • Each pattern is introduced in a separate commit, and each commit passes tests.
  • Tests exist at unit level for each pattern.
  • An ADR exists documenting the decision.
  • You can explain, in one sentence per pattern, which pressure it is absorbing and what it costs.