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. Compare wrapper options. Add logging and optional caching with behavior tests; use functions or decorators when justified. Commit coherent steps.
  4. Choose assembly. Compare a construction function with a Factory abstraction; choose based on configuration pressure and document the cost.
  5. Extend tests throughout. Each pricing rule, chosen wrapper, and an end-to-end path; test expiry and wrapper order when caching is enabled.
  6. Write an ADR. Name the actual assembly decision; compare a function/table approach with the chosen pattern composition and record rejected alternatives.

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 coherent implementation step passes its contract tests; no minimum pattern count.
  • 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.