# Design Patterns Walkthrough — Learn by Doing

## Step 1: Strategy in Practice

**Task:** Implement a `PaymentProcessor` that can use different payment strategies (CreditCard, PayPal, Crypto). The processor should accept a strategy and delegate the `pay(amount)` call.

**Question:** What would you need to change to add Apple Pay? Would you edit the processor or add a new strategy class?

**Checkpoint:** The user has a working strategy setup and understands open/closed extension.

---

## Step 2: Factory for Object Creation

**Task:** Create a `NotificationFactory` that returns the right notification type (Email, SMS, Push) based on a string or enum. The factory encapsulates the `if/switch` logic.

**Question:** Where should configuration (e.g., API keys for each channel) live — inside the factory, or passed in? What are the tradeoffs?

**Checkpoint:** The user has a factory that returns typed instances based on input.

---

## Step 3: Observer for Event Handling

**Task:** Build a simple `Subject` class: `subscribe(callback)`, `unsubscribe(callback)`, `notify(data)`. Use it to let a "form" notify "validators" and "analytics" when the user submits.

**Question:** What happens if a subscriber throws? How might you make the observer more robust?

**Checkpoint:** The user has a working pub-sub and multiple subscribers.

---

## Step 4: Decorator for Layered Behavior

<!-- hint:code language="javascript" highlight="1,3" -->

**Task:** Create a `Logger` interface with `log(msg)`. Implement `ConsoleLogger`. Then create `TimestampDecorator` and `LevelDecorator` that wrap a logger and add behavior. Compose them: `TimestampDecorator(LevelDecorator(ConsoleLogger))`.

**Question:** What order should decorators be applied? Does it matter?

**Checkpoint:** The user can stack decorators and explain composition order.

---

## Step 5: Adapter for Legacy Code

**Task:** You have a function `fetchData(callback)` that uses callbacks. Create an adapter so it can be used with `async/await` or returns a Promise.

**Question:** Does the adapter change the behavior of the legacy code, or just its interface?

**Checkpoint:** The user can wrap a callback API in a Promise-based interface.

---

## Step 6: When *Not* to Use a Pattern

<!-- hint:buttons type="single" prompt="For a simple utility function, which applies?" options="Singleton,Factory,Strategy,No pattern" -->
<!-- hint:card type="concept" title="YAGNI: You Aren't Gonna Need It" -->

**Task:** Consider a small feature (e.g., a utility function). Would Singleton, Factory, or Strategy apply? If not, explain why. "No pattern" is a valid answer.

**Question:** What's the cost of over-applying patterns? When does YAGNI trump pattern elegance?

**Checkpoint:** The user can articulate when patterns add value vs unnecessary complexity.
